diff --git a/gateway/platforms/api_server.py b/gateway/platforms/api_server.py index e4ebd27146..18ab1fab97 100644 --- a/gateway/platforms/api_server.py +++ b/gateway/platforms/api_server.py @@ -3488,7 +3488,7 @@ class APIServerAdapter(OpenAICompatRoutesMixin, BasePlatformAdapter): task = asyncio.create_task(asyncio.to_thread(fire_fn, *fire_args, adapters=adapters, loop=loop)) reservation["detached"] = True task.add_done_callback(lambda _task: _release_pending_api_work(self, reservation)) - self._track_background_task(task) + self._track_background_task(task, tolerate_missing=True) return web.json_response({"status": "accepted", "job_id": job_id}, status=202) if not provider_supports_split_fire(provider): @@ -3508,9 +3508,16 @@ class APIServerAdapter(OpenAICompatRoutesMixin, BasePlatformAdapter): # -- Agent execution -------------------------------------------------------------- - def _track_background_task(self, task) -> None: - """Register a task in ``_background_tasks`` (tolerates test doubles) with auto-discard.""" - with suppress(TypeError, AttributeError): + def _track_background_task(self, task, *, tolerate_missing: bool = False) -> None: + """Register a task in ``_background_tasks`` (tolerates test doubles) with auto-discard. + ``tolerate_missing`` (cron fire paths) also swallows AttributeError from the whole + registration; the run/sweep paths only tolerate an unhashable task.""" + if tolerate_missing: + with suppress(TypeError, AttributeError): + self._background_tasks.add(task) + task.add_done_callback(self._background_tasks.discard) + return + with suppress(TypeError): self._background_tasks.add(task) if hasattr(task, "add_done_callback"): task.add_done_callback(self._background_tasks.discard) diff --git a/hermes_cli/update_cmd_fleet.py b/hermes_cli/update_cmd_fleet.py index eebb6732a6..f81bf0b4d8 100644 --- a/hermes_cli/update_cmd_fleet.py +++ b/hermes_cli/update_cmd_fleet.py @@ -33,8 +33,9 @@ _LIST_GATEWAY_UNITS = ["list-units", "hermes-gateway*", "hermes-serve*", "--plai def _write_gateway_update_exit_code(ok: bool) -> None: from hermes_cli.update_cmd import get_hermes_home + path = get_hermes_home() / ".update_exit_code" with suppress(OSError): - (get_hermes_home() / ".update_exit_code").write_text("0" if ok else "1", encoding="utf-8") + path.write_text("0" if ok else "1", encoding="utf-8") def _fleet_restart_pending_marker_path() -> Path: diff --git a/tools/patch_parser.py b/tools/patch_parser.py index 74ce9fe331..86fc16ae98 100644 --- a/tools/patch_parser.py +++ b/tools/patch_parser.py @@ -298,11 +298,12 @@ def apply_v4a_operations(operations: List[PatchOperation], file_ops: Any) -> 'Pa def _write_file_accepts_pre_content(file_ops: Any) -> bool: """Whether ``file_ops.write_file`` accepts ``pre_content`` — read from the signature, not by catching TypeError around the call, so a TypeError raised *inside* it can't double-write.""" - with contextlib.suppress(TypeError, ValueError): + try: params = inspect.signature(file_ops.write_file).parameters - return "pre_content" in params or any( - p.kind is inspect.Parameter.VAR_KEYWORD for p in params.values()) - return False + except (TypeError, ValueError): + return False + return "pre_content" in params or any( + p.kind is inspect.Parameter.VAR_KEYWORD for p in params.values()) def _apply_add(op: PatchOperation, file_ops: Any) -> ApplyResult: diff --git a/tools/skills_sync.py b/tools/skills_sync.py index c6f842a547..cb1f2b21af 100644 --- a/tools/skills_sync.py +++ b/tools/skills_sync.py @@ -19,8 +19,9 @@ from typing import Dict, Iterator, List, Optional, Set, Tuple # Force UTF-8 stdout/stderr: GBK-style Windows locales can't encode the glyphs # printed here (✓ ↑ →), and install.ps1 parses this script's stdout as UTF-8. for _stream in (sys.stdout, sys.stderr): - with suppress(AttributeError, ValueError, TypeError): - _stream.reconfigure(encoding="utf-8", errors="replace") + if hasattr(_stream, "reconfigure"): + with suppress(ValueError, TypeError): + _stream.reconfigure(encoding="utf-8", errors="replace") from hermes_constants import get_bundled_skills_dir, get_hermes_home, get_optional_skills_dir from agent.skill_utils import ESSENTIAL_SKILLS, is_excluded_skill_path from tools.skill_usage import _read_skill_name, read_suppressed_names # noqa: F401 (re-exported)