Spaces:
Running
Running
| #!/usr/bin/env python3 | |
| """Patch hermes-agent: sandbox isolation DISABLED (2026-05-09 emergency fix). | |
| The original patch had a CRITICAL indentation bug in the Popen hook: | |
| old_popen = "proc = subprocess.Popen(\n args," # no leading spaces | |
| new_popen = " # Hermes Bot patch: ...\n" # 8 leading spaces | |
| → str.replace doubled indentation (8+8=16 spaces) → IndentationError | |
| → local.py failed to import → terminal tool completely broken | |
| This no-op version preserves the file so start.sh doesn't error, | |
| but does NOT inject any code into local.py. | |
| Re-enable after rewriting with correct indentation matching (include | |
| leading spaces in old_popen to prevent double-indentation). | |
| """ | |
| import sys | |
| import os | |
| import glob | |
| def patch_file(filepath: str) -> bool: | |
| """No-op: sandbox isolation patch is disabled.""" | |
| # If previously patched, REMOVE the sandbox code to restore clean state | |
| with open(filepath, "r") as f: | |
| content = f.read() | |
| if "sandbox_wrap" not in content: | |
| print(f" [local.py] Clean (no sandbox code found)") | |
| return True | |
| # Remove the sandbox wrapper code block | |
| sandbox_start = content.find("# ── Hermes Bot patch: Sandbox isolation for dangerous commands ──") | |
| if sandbox_start < 0: | |
| sandbox_start = content.find("# Hermes Bot patch: Sandbox isolation for dangerous commands") | |
| if sandbox_start < 0: | |
| print(f" [local.py] sandbox_wrap found but no injection marker — manual cleanup needed") | |
| return True | |
| # Find the insertion point: the line before the sandbox block | |
| # Walk backwards to find the start of the injected block | |
| line_start = content.rfind("\n", 0, sandbox_start) | |
| if line_start < 0: | |
| line_start = 0 | |
| else: | |
| line_start += 1 # skip the \n | |
| # Find the end of the sandbox code block | |
| # The block ends with a blank line before the next original code | |
| # Look for the pattern that indicates end of injected code | |
| # The sandbox code block ends with the closing of should_sandbox function | |
| sandbox_end_markers = [ | |
| "\n\ndef _resolve_safe_cwd", # original function after injection point | |
| "\n\ndef _build_provider_env", # alternative | |
| "\n\nclass LocalEnvironment", # if injected before class | |
| ] | |
| sandbox_end = -1 | |
| for marker in sandbox_end_markers: | |
| pos = content.find(marker, sandbox_start) | |
| if pos > 0: | |
| sandbox_end = pos | |
| break | |
| if sandbox_end < 0: | |
| # Fallback: find the next top-level def or class after sandbox_start | |
| import re | |
| m = re.search(r'\n(def |class )', content[sandbox_start + 100:]) | |
| if m: | |
| sandbox_end = sandbox_start + 100 + m.start() | |
| else: | |
| print(f" [local.py] Could not find end of sandbox block — skipping cleanup") | |
| return False | |
| # Also remove the hook code from _run_bash if present | |
| hook_pattern = " # Hermes Bot patch: auto-sandbox dangerous commands\n" | |
| new_content = content[line_start:sandbox_end] | |
| new_content2 = new_content.replace(hook_pattern, "") | |
| if len(new_content2) < len(new_content): | |
| # Remove the if should_sandbox block too | |
| import re | |
| new_content2 = re.sub( | |
| r'\n if should_sandbox\(cmd_string\):\n.*?(?=\n proc = subprocess\.Popen)', | |
| '\n', | |
| new_content2, | |
| flags=re.DOTALL, | |
| ) | |
| content = content[:line_start] + new_content2 + content[sandbox_end:] | |
| print(f" [local.py] Removed sandbox hook from _run_bash") | |
| else: | |
| content = content[:line_start] + content[sandbox_end:] | |
| print(f" [local.py] Removed sandbox wrapper code block") | |
| with open(filepath, "w") as f: | |
| f.write(content) | |
| print(f" [local.py] Sandbox isolation REMOVED (emergency fix)") | |
| return True | |
| if __name__ == "__main__": | |
| print("Sandbox isolation patch: DISABLED (emergency fix 2026-05-09)") | |
| print(" Reason: indentation bug caused local.py IndentationError") | |
| candidates = [ | |
| "/app/hermes-agent/tools/environments/local.py", | |
| ] | |
| candidates.extend( | |
| glob.glob("/app/venv/lib/**/tools/environments/local.py", recursive=True) | |
| ) | |
| filepath = None | |
| for c in candidates: | |
| if os.path.isfile(c): | |
| filepath = c | |
| break | |
| if not filepath: | |
| print(" local.py not found — nothing to do") | |
| sys.exit(0) | |
| patch_file(filepath) | |
| print(" Terminal tool should now work normally") | |