fix(claw): warn if OpenClaw is running before migration - #8102
fix(claw): warn if OpenClaw is running before migration#8102fancydirty wants to merge 3 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a pre-migration safety warning to hermes claw migrate by detecting whether OpenClaw appears to still be running, to reduce bot-token session conflicts during migration (Issue #7907).
Changes:
- Introduces
_is_openclaw_running()to detect OpenClaw processes (pgrep on Unix, tasklist on Windows). - Adds
_warn_if_openclaw_running()that warns and prompts to continue (skippable with--yes) and integrates it into the migrate flow. - Adds unit tests covering detection and warning behavior, plus a fixture to prevent prompts during existing migrate tests.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
hermes_cli/claw.py |
Adds OpenClaw-running detection + warning prompt and calls it before gateway checks in migrate. |
tests/hermes_cli/test_claw.py |
Adds tests for detection/warning helpers and an autouse fixture to avoid interactive prompts in migrate tests. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| try: | ||
| result = subprocess.run( | ||
| ["tasklist", "/FI", "IMAGENAME eq node.exe"], | ||
| capture_output=True, text=True, timeout=5 | ||
| ) | ||
| output = result.stdout.lower() | ||
| return "openclaw" in output or "clawd" in output | ||
| except Exception: | ||
| return False | ||
|
|
There was a problem hiding this comment.
Windows detection likely won’t work as written: tasklist output does not include process command lines (only the image name, PID, etc.), so searching stdout for openclaw/clawd will almost always return false even when OpenClaw is running under node.exe. Consider querying command lines via PowerShell/WMI (e.g., Get-CimInstance Win32_Process filtering on node.exe and inspecting CommandLine) or checking for an actual clawd.exe/openclaw*.exe image name if applicable, and update the tests accordingly.
| try: | |
| result = subprocess.run( | |
| ["tasklist", "/FI", "IMAGENAME eq node.exe"], | |
| capture_output=True, text=True, timeout=5 | |
| ) | |
| output = result.stdout.lower() | |
| return "openclaw" in output or "clawd" in output | |
| except Exception: | |
| return False | |
| powershell_cmd = [ | |
| "powershell", | |
| "-NoProfile", | |
| "-Command", | |
| ( | |
| "$procs = Get-CimInstance Win32_Process | Where-Object { " | |
| "$_.Name -eq 'node.exe' -or " | |
| "$_.Name -eq 'clawd.exe' -or " | |
| "$_.Name -like 'openclaw*.exe' " | |
| "}; " | |
| "$procs | ForEach-Object { ($_.Name + ' ' + $_.CommandLine) }" | |
| ), | |
| ] | |
| try: | |
| result = subprocess.run( | |
| powershell_cmd, | |
| capture_output=True, | |
| text=True, | |
| timeout=5, | |
| ) | |
| output = (result.stdout or "").lower() | |
| if "openclaw" in output or "clawd" in output: | |
| return True | |
| except (FileNotFoundError, subprocess.TimeoutExpired, OSError): | |
| pass | |
| for image_name in ("clawd.exe", "openclaw.exe"): | |
| try: | |
| result = subprocess.run( | |
| ["tasklist", "/FI", f"IMAGENAME eq {image_name}"], | |
| capture_output=True, | |
| text=True, | |
| timeout=5, | |
| ) | |
| if image_name in (result.stdout or "").lower(): | |
| return True | |
| except (FileNotFoundError, subprocess.TimeoutExpired, OSError): | |
| continue | |
| return False |
| print() | ||
| print_error("OpenClaw appears to be running.") | ||
| print_info( | ||
| "Messaging platforms (Telegram, Discord, Slack) only allow one " | ||
| "active session per bot token. If you continue, both OpenClaw and " | ||
| "Hermes may try to use the same token, causing disconnects." | ||
| ) | ||
| print_info("Recommendation: stop OpenClaw before migrating.") | ||
| print() | ||
| if not auto_yes and not prompt_yes_no("Continue anyway?", default=False): | ||
| print_info("Migration cancelled. Stop OpenClaw and try again.") | ||
| sys.exit(0) |
There was a problem hiding this comment.
_warn_if_openclaw_running() can prompt before the later non-interactive guard in _cmd_migrate (the sys.stdin.isatty() check). In a non-interactive session without --yes, prompt_yes_no() will hit EOF and exit(1), preventing the intended “preview only” behavior. Consider short-circuiting here when stdin isn’t a TTY (e.g., print the warning and return, or treat non-interactive as auto-yes/auto-no consistently with the rest of the command).
| def test_returns_true_on_windows_tasklist(self): | ||
| with patch.object(claw_mod, "sys") as mock_sys: | ||
| mock_sys.platform = "win32" | ||
| with patch.object(claw_mod, "subprocess") as mock_subprocess: | ||
| mock_subprocess.run.return_value = MagicMock( | ||
| returncode=0, | ||
| stdout="node.exe openclaw-gateway", | ||
| ) | ||
| assert claw_mod._is_openclaw_running() is True | ||
|
|
||
| def test_returns_false_on_windows_when_not_found(self): | ||
| with patch.object(claw_mod, "sys") as mock_sys: | ||
| mock_sys.platform = "win32" | ||
| with patch.object(claw_mod, "subprocess") as mock_subprocess: | ||
| mock_subprocess.run.return_value = MagicMock( | ||
| returncode=0, | ||
| stdout="node.exe some-other-app", | ||
| ) | ||
| assert claw_mod._is_openclaw_running() is False |
There was a problem hiding this comment.
These Windows tests assume tasklist returns command-line details like "node.exe openclaw-gateway", but tasklist output typically does not include the process command line. As a result, the test suite would validate behavior that can’t happen on real Windows, and would miss regressions once Windows detection is implemented correctly (e.g., via PowerShell/WMI). Update the tests to match the chosen Windows detection mechanism and real tasklist output formats.
Add _is_openclaw_running() and _warn_if_openclaw_running() to detect OpenClaw processes (via pgrep/tasklist) before hermes claw migrate. Warns the user that messaging platforms only allow one active session per bot token, and lets them cancel or continue. Fixes NousResearch#7907
…ctive prompt - Use PowerShell to inspect node.exe command lines on Windows, since tasklist output does not include them. - Also check for dedicated openclaw.exe/clawd.exe processes. - Skip the interactive prompt in non-interactive sessions so the preview-only behavior is preserved. - Update tests accordingly. Relates to NousResearch#7907
0192ed2 to
a68ccaa
Compare
Prevents stale cooldown from suppressing summaries after context compression triggers a session split.
…port Combines detection from both PRs into _detect_openclaw_processes(): - Cross-platform process scan (pgrep/tasklist/PowerShell) from PR #8102 - systemd service check from PR #8555 - Returns list[str] with details about what's found Fixes in cleanup warning (from PR #8555): - print_warning -> print_error/print_info (print_warning not in import chain) - Added isatty() guard for non-interactive sessions - Removed duplicate _check_openclaw_running() in favor of shared function Updated all tests to match new API.
…port Combines detection from both PRs into _detect_openclaw_processes(): - Cross-platform process scan (pgrep/tasklist/PowerShell) from PR #8102 - systemd service check from PR #8555 - Returns list[str] with details about what's found Fixes in cleanup warning (from PR #8555): - print_warning -> print_error/print_info (print_warning not in import chain) - Added isatty() guard for non-interactive sessions - Removed duplicate _check_openclaw_running() in favor of shared function Updated all tests to match new API.
|
Merged via PR #8663. Your OpenClaw detection function and comprehensive tests were cherry-picked onto current main with your authorship preserved. Combined with PR #8555's systemd check and cleanup-side warning into a unified solution. Thanks @fancydirty! |
…port Combines detection from both PRs into _detect_openclaw_processes(): - Cross-platform process scan (pgrep/tasklist/PowerShell) from PR NousResearch#8102 - systemd service check from PR NousResearch#8555 - Returns list[str] with details about what's found Fixes in cleanup warning (from PR NousResearch#8555): - print_warning -> print_error/print_info (print_warning not in import chain) - Added isatty() guard for non-interactive sessions - Removed duplicate _check_openclaw_running() in favor of shared function Updated all tests to match new API.
…port Combines detection from both PRs into _detect_openclaw_processes(): - Cross-platform process scan (pgrep/tasklist/PowerShell) from PR NousResearch#8102 - systemd service check from PR NousResearch#8555 - Returns list[str] with details about what's found Fixes in cleanup warning (from PR NousResearch#8555): - print_warning -> print_error/print_info (print_warning not in import chain) - Added isatty() guard for non-interactive sessions - Removed duplicate _check_openclaw_running() in favor of shared function Updated all tests to match new API.
…port Combines detection from both PRs into _detect_openclaw_processes(): - Cross-platform process scan (pgrep/tasklist/PowerShell) from PR NousResearch#8102 - systemd service check from PR NousResearch#8555 - Returns list[str] with details about what's found Fixes in cleanup warning (from PR NousResearch#8555): - print_warning -> print_error/print_info (print_warning not in import chain) - Added isatty() guard for non-interactive sessions - Removed duplicate _check_openclaw_running() in favor of shared function Updated all tests to match new API.
Detects running OpenClaw processes (via
pgrepon Unix ortaskliston Windows) beforehermes claw migrateand warns the user. Messaging platforms only allow one active session per bot token; running both simultaneously causes token fights and disconnects._is_openclaw_running()helper_warn_if_openclaw_running()with a yes/no prompt (skippable with--yes)Fixes #7907