mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-02 02:01:47 +00:00
fix: preserve symlinks during atomic file writes (#16743)
os.replace(tmp, path) replaces the symlink itself with a regular file, breaking users who symlink config.yaml, SOUL.md, or .env from ~/.hermes/ to a dotfiles repo or managed profile package. Fix: resolve symlinks via os.path.realpath() before os.replace(), so the real file is overwritten in-place while the symlink survives. Fixed in 7 files covering all os.replace call sites: - utils.py (atomic_json_write, atomic_yaml_write — fixes save_config) - hermes_cli/config.py (env sanitizer, save_env_value, remove_env_value) - tools/skill_manager_tool.py (_atomic_write_text — SOUL.md writes) - tools/memory_tool.py (memory file writes) - tools/skills_sync.py (manifest writes) - cron/jobs.py (job state + output file writes) - agent/shell_hooks.py (hook file writes) Fixes NousResearch/hermes-agent#16743
This commit is contained in:
parent
1369dae226
commit
3ab97a32d1
7 changed files with 38 additions and 13 deletions
|
|
@ -3666,7 +3666,9 @@ def sanitize_env_file() -> int:
|
|||
f.writelines(sanitized)
|
||||
f.flush()
|
||||
os.fsync(f.fileno())
|
||||
os.replace(tmp_path, env_path)
|
||||
# Resolve symlinks so os.replace writes to the real file (GitHub #16743).
|
||||
real_path = os.path.realpath(env_path) if os.path.islink(env_path) else env_path
|
||||
os.replace(tmp_path, real_path)
|
||||
except BaseException:
|
||||
try:
|
||||
os.unlink(tmp_path)
|
||||
|
|
@ -3769,7 +3771,9 @@ def save_env_value(key: str, value: str):
|
|||
f.writelines(lines)
|
||||
f.flush()
|
||||
os.fsync(f.fileno())
|
||||
os.replace(tmp_path, env_path)
|
||||
# Resolve symlinks so os.replace writes to the real file (GitHub #16743).
|
||||
real_path = os.path.realpath(env_path) if os.path.islink(env_path) else env_path
|
||||
os.replace(tmp_path, real_path)
|
||||
# Restore original permissions before _secure_file may tighten them.
|
||||
if original_mode is not None:
|
||||
try:
|
||||
|
|
@ -3825,7 +3829,9 @@ def remove_env_value(key: str) -> bool:
|
|||
f.writelines(new_lines)
|
||||
f.flush()
|
||||
os.fsync(f.fileno())
|
||||
os.replace(tmp_path, env_path)
|
||||
# Resolve symlinks so os.replace writes to the real file (GitHub #16743).
|
||||
real_path = os.path.realpath(env_path) if os.path.islink(env_path) else env_path
|
||||
os.replace(tmp_path, real_path)
|
||||
if original_mode is not None:
|
||||
try:
|
||||
os.chmod(env_path, original_mode)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue