Spaces:
Running
Running
| #!/usr/bin/env python3 | |
| """Patch hermes-agent gateway to auto-resolve relative media paths. | |
| ROOT CAUSE: When the LLM uses write_file, it often saves files with relative | |
| paths like "广东天气预报.md" or "/tmp/广东天气预报.md", then puts | |
| "MEDIA:广东天气预报.md" in the response. The gateway's extract_media() | |
| parses this bare filename, but the subsequent send_document() call fails | |
| because the path is relative and os.path.isfile() returns False. | |
| FIX: After extract_media() returns the media_files list, scan each path: | |
| 1. If already absolute and exists → keep as-is | |
| 2. If relative → search well-known directories (/tmp/, /data/hermes/uploads/, | |
| current working directory, HERMES_HOME) for a file with that name | |
| 3. Replace the path with the resolved absolute path | |
| 4. If still not found → keep the original (will fail with clear error) | |
| This is a surgical patch to the _deliver_response() method in base.py, | |
| inserted right after the "media_files, response = self.extract_media(response)" | |
| line. | |
| """ | |
| import re | |
| import sys | |
| import os | |
| import glob | |
| def patch_file(filepath: str): | |
| with open(filepath, 'r') as f: | |
| content = f.read() | |
| # Find the insertion point: right after extract_media() call | |
| old = """\ | |
| # Extract MEDIA:<path> tags (from TTS tool) before other processing | |
| media_files, response = self.extract_media(response)""" | |
| new = """\ | |
| # Extract MEDIA:<path> tags (from TTS tool) before other processing | |
| media_files, response = self.extract_media(response) | |
| # Auto-resolve relative media paths to absolute paths. | |
| # The LLM often uses bare filenames in MEDIA: tags (e.g. "report.md") | |
| # which fail because send_document() can't find them. | |
| _media_search_dirs = ['/tmp', '/data/hermes/uploads', '/data', os.getcwd()] | |
| _hermes_home = os.path.expanduser('~/.hermes') | |
| if _hermes_home not in _media_search_dirs: | |
| _media_search_dirs.append(_hermes_home) | |
| _resolved_media = [] | |
| for _mpath, _mvoice in media_files: | |
| if os.path.isabs(_mpath) and os.path.isfile(_mpath): | |
| _resolved_media.append((_mpath, _mvoice)) | |
| continue | |
| # Try to find the file in well-known directories | |
| _basename = os.path.basename(_mpath) | |
| _found = None | |
| for _search_dir in _media_search_dirs: | |
| _candidate = os.path.join(_search_dir, _basename) | |
| if os.path.isfile(_candidate): | |
| _found = _candidate | |
| break | |
| if _found: | |
| logger.info("[%s] Resolved relative media path '%s' -> '%s'", self.name, _mpath, _found) | |
| _resolved_media.append((_found, _mvoice)) | |
| else: | |
| # Keep original — will fail with a clear error message | |
| _resolved_media.append((_mpath, _mvoice)) | |
| logger.warning("[%s] Could not resolve media path '%s' — searched %s", self.name, _mpath, _media_search_dirs) | |
| media_files = _resolved_media""" | |
| if old not in content: | |
| print(f"WARNING: Could not find insertion point in {filepath}", file=sys.stderr) | |
| print("The upstream code may have changed. Skipping this patch.", file=sys.stderr) | |
| sys.exit(0) | |
| content = content.replace(old, new, 1) | |
| with open(filepath, 'w') as f: | |
| f.write(content) | |
| print(f"Patched {filepath}: auto-resolve relative media paths before sending") | |
| if __name__ == "__main__": | |
| candidates = [ | |
| "/app/hermes-agent/gateway/platforms/base.py", | |
| ] | |
| candidates.extend(glob.glob("/app/venv/lib/**/gateway/platforms/base.py", recursive=True)) | |
| filepath = None | |
| for c in candidates: | |
| if os.path.isfile(c): | |
| filepath = c | |
| break | |
| if not filepath: | |
| print("WARNING: base.py not found in any candidate location", file=sys.stderr) | |
| print(f"Checked: {candidates}", file=sys.stderr) | |
| print("Skipping patch_resolve_media_paths.", file=sys.stderr) | |
| sys.exit(0) | |
| patch_file(filepath) | |