mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-31 19:16:29 +00:00
fix: add encoding="utf-8" to Path.write_text() calls (P1)
Path.write_text() without encoding defaults to system locale encoding. On Windows (cp1252), this silently corrupts non-ASCII content written to JSON files, config files, and cache files. This is the write-side counterpart to the read_text() encoding fix (PR #56115). PLW1514 only covers open() calls — Path methods are unguarded by ruff. 39 instances across 16 files, all passing py_compile. Files changed: - agent/copilot_acp_client.py (1) - tools/web_tools.py (1) - tools/xai_http.py (1) - tools/skills_hub.py (8) - gateway/slash_commands.py (1) - gateway/run.py (5) - gateway/dead_targets.py (1) - gateway/delivery.py (2) - gateway/platforms/qqbot/adapter.py (1) - hermes_cli/gateway.py (1) - hermes_cli/banner.py (1) - hermes_cli/service_manager.py (5) - hermes_cli/container_boot.py (5) - hermes_cli/uninstall.py (1) - hermes_cli/main.py (2) - hermes_cli/profiles.py (3)
This commit is contained in:
parent
44649e69f4
commit
411a686de2
8 changed files with 18 additions and 18 deletions
|
|
@ -462,7 +462,7 @@ def _register_service(scandir: Path, profile: str, *, start: bool) -> None:
|
|||
run.chmod(0o755)
|
||||
|
||||
finish = tmp_dir / "finish"
|
||||
finish.write_text(S6ServiceManager._render_finish_script())
|
||||
finish.write_text(S6ServiceManager._render_finish_script(), encoding="utf-8")
|
||||
finish.chmod(0o755)
|
||||
|
||||
# Persistent log rotation (OQ8-C).
|
||||
|
|
|
|||
|
|
@ -4806,7 +4806,7 @@ def _gateway_prompt(prompt_text: str, default: str = "", timeout: float = 300.0)
|
|||
"id": str(_uuid.uuid4()),
|
||||
}
|
||||
tmp = prompt_path.with_suffix(".tmp")
|
||||
tmp.write_text(_json.dumps(payload))
|
||||
tmp.write_text(_json.dumps(payload), encoding="utf-8")
|
||||
tmp.replace(prompt_path)
|
||||
|
||||
# Poll for response
|
||||
|
|
@ -11905,7 +11905,7 @@ def _cmd_update_impl(args, gateway_mode: bool):
|
|||
if gateway_mode:
|
||||
_exit_code_path = get_hermes_home() / ".update_exit_code"
|
||||
try:
|
||||
_exit_code_path.write_text("0")
|
||||
_exit_code_path.write_text("0", encoding="utf-8")
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
|
|
|
|||
|
|
@ -458,7 +458,7 @@ def create_wrapper_script(name: str, target: Optional[str] = None) -> Optional[P
|
|||
if is_windows:
|
||||
wrapper_path = wrapper_dir / f"{canon}.bat"
|
||||
try:
|
||||
wrapper_path.write_text(f"@echo off\r\nhermes -p {profile} %*\r\n")
|
||||
wrapper_path.write_text(f"@echo off\r\nhermes -p {profile} %*\r\n", encoding="utf-8")
|
||||
return wrapper_path
|
||||
except OSError as e:
|
||||
print(f"⚠ Could not create wrapper at {wrapper_path}: {e}")
|
||||
|
|
@ -467,7 +467,7 @@ def create_wrapper_script(name: str, target: Optional[str] = None) -> Optional[P
|
|||
wrapper_path = wrapper_dir / canon
|
||||
try:
|
||||
hermes_exe = shutil.which("hermes") or "hermes"
|
||||
wrapper_path.write_text(f'#!/bin/sh\nexec {shlex.quote(hermes_exe)} -p {profile} "$@"\n')
|
||||
wrapper_path.write_text(f'#!/bin/sh\nexec {shlex.quote(hermes_exe)} -p {profile} "$@"\n', encoding="utf-8")
|
||||
wrapper_path.chmod(wrapper_path.stat().st_mode | stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH)
|
||||
return wrapper_path
|
||||
except OSError as e:
|
||||
|
|
@ -1825,7 +1825,7 @@ def set_active_profile(name: str) -> None:
|
|||
else:
|
||||
# Atomic write
|
||||
tmp = path.with_suffix(".tmp")
|
||||
tmp.write_text(canon + "\n")
|
||||
tmp.write_text(canon + "\n", encoding="utf-8")
|
||||
tmp.replace(path)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -995,7 +995,7 @@ class S6ServiceManager:
|
|||
run_path.chmod(0o755)
|
||||
|
||||
finish_path = tmp_dir / "finish"
|
||||
finish_path.write_text(self._render_finish_script())
|
||||
finish_path.write_text(self._render_finish_script(), encoding="utf-8")
|
||||
finish_path.chmod(0o755)
|
||||
|
||||
# Persistent log rotation (OQ8-C).
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ def remove_path_from_shell_configs():
|
|||
new_content = new_content.replace('\n\n\n', '\n\n')
|
||||
|
||||
if new_content != original_content:
|
||||
config_path.write_text(new_content)
|
||||
config_path.write_text(new_content, encoding="utf-8")
|
||||
removed_from.append(config_path)
|
||||
|
||||
except Exception as e:
|
||||
|
|
|
|||
|
|
@ -1154,7 +1154,7 @@ class GitHubSource(SkillSource):
|
|||
index_cache_dir.mkdir(parents=True, exist_ok=True)
|
||||
cache_file = index_cache_dir / f"{key}.json"
|
||||
try:
|
||||
cache_file.write_text(json.dumps(data, ensure_ascii=False))
|
||||
cache_file.write_text(json.dumps(data, ensure_ascii=False), encoding="utf-8")
|
||||
except OSError as e:
|
||||
logger.debug("Could not write cache: %s", e)
|
||||
|
||||
|
|
@ -3370,12 +3370,12 @@ def _write_index_cache(key: str, data: Any) -> None:
|
|||
ignore_file = _hub_dir() / ".ignore"
|
||||
if not ignore_file.exists():
|
||||
try:
|
||||
ignore_file.write_text("# Exclude hub internals from search tools\n*\n")
|
||||
ignore_file.write_text("# Exclude hub internals from search tools\n*\n", encoding="utf-8")
|
||||
except OSError:
|
||||
pass
|
||||
cache_file = index_cache_dir / f"{key}.json"
|
||||
try:
|
||||
cache_file.write_text(json.dumps(data, ensure_ascii=False, default=str))
|
||||
cache_file.write_text(json.dumps(data, ensure_ascii=False, default=str), encoding="utf-8")
|
||||
except OSError as e:
|
||||
logger.debug("Could not write cache: %s", e)
|
||||
|
||||
|
|
@ -3415,7 +3415,7 @@ class HubLockFile:
|
|||
|
||||
def save(self, data: dict) -> None:
|
||||
self.path.parent.mkdir(parents=True, exist_ok=True)
|
||||
self.path.write_text(json.dumps(data, indent=2, ensure_ascii=False) + "\n")
|
||||
self.path.write_text(json.dumps(data, indent=2, ensure_ascii=False) + "\n", encoding="utf-8")
|
||||
|
||||
def record_install(
|
||||
self,
|
||||
|
|
@ -3490,7 +3490,7 @@ class TapsManager:
|
|||
|
||||
def save(self, taps: List[dict]) -> None:
|
||||
self.path.parent.mkdir(parents=True, exist_ok=True)
|
||||
self.path.write_text(json.dumps({"taps": taps}, indent=2) + "\n")
|
||||
self.path.write_text(json.dumps({"taps": taps}, indent=2) + "\n", encoding="utf-8")
|
||||
|
||||
def add(self, repo: str, path: str = "skills/") -> bool:
|
||||
"""Add a tap. Returns False if already exists."""
|
||||
|
|
@ -3549,11 +3549,11 @@ def ensure_hub_dirs() -> None:
|
|||
_quarantine_dir().mkdir(exist_ok=True)
|
||||
_index_cache_dir().mkdir(exist_ok=True)
|
||||
if not lock_file.exists():
|
||||
lock_file.write_text('{"version": 1, "installed": {}}\n')
|
||||
lock_file.write_text('{"version": 1, "installed": {}}\n', encoding="utf-8")
|
||||
if not audit_log.exists():
|
||||
audit_log.touch()
|
||||
if not taps_file.exists():
|
||||
taps_file.write_text('{"taps": []}\n')
|
||||
taps_file.write_text('{"taps": []}\n', encoding="utf-8")
|
||||
|
||||
|
||||
def quarantine_bundle(bundle: SkillBundle) -> Path:
|
||||
|
|
@ -3857,7 +3857,7 @@ def _load_hermes_index() -> Optional[dict]:
|
|||
# Cache locally
|
||||
try:
|
||||
hermes_index_cache_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
hermes_index_cache_file.write_text(json.dumps(data))
|
||||
hermes_index_cache_file.write_text(json.dumps(data), encoding="utf-8")
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
|
|
|
|||
|
|
@ -422,7 +422,7 @@ def _web_requires_env() -> list[str]:
|
|||
DEFAULT_EXTRACT_CHAR_LIMIT = 15000
|
||||
|
||||
# Hard ceiling on the full-text file written to cache/web. The truncate-store
|
||||
# path otherwise calls path.write_text(content) with no upper bound, so a
|
||||
# path otherwise calls path.write_text(content, encoding="utf-8") with no upper bound, so a
|
||||
# multi-MB page (some backends return very large markdown) writes unbounded
|
||||
# bytes to disk on every extract. Cap the stored copy; the model only ever
|
||||
# sees char_limit anyway, and a 2MB page is already far more than any single
|
||||
|
|
|
|||
|
|
@ -234,7 +234,7 @@ def maybe_mark_xai_storage_notice_seen(section_name: str) -> Optional[str]:
|
|||
marker = marker_dir / f"{section_name}_xai_storage_notice_seen"
|
||||
if marker.exists():
|
||||
return None
|
||||
marker.write_text(datetime.datetime.now(datetime.UTC).isoformat() + "\n")
|
||||
marker.write_text(datetime.datetime.now(datetime.UTC).isoformat() + "\n", encoding="utf-8")
|
||||
return notice
|
||||
except Exception:
|
||||
return notice
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue