refactor: enhance error handling with structured logging across multiple modules

- Updated various modules including cli.py, run_agent.py, gateway, and tools to replace silent exception handling with structured logging.
- Improved error messages to provide more context, aiding in debugging and monitoring.
- Ensured consistent logging practices throughout the codebase, enhancing traceability and maintainability.
This commit is contained in:
teknium1 2026-02-21 03:32:11 -08:00
parent cbff1b818c
commit 748fd3db88
14 changed files with 134 additions and 110 deletions

View file

@ -31,6 +31,8 @@ import uuid
from typing import Any, Dict, List, Optional
# Availability gate: UDS requires a POSIX OS
logger = logging.getLogger(__name__)
SANDBOX_AVAILABLE = sys.platform != "win32"
# The 7 tools allowed inside the sandbox. The intersection of this list
@ -488,8 +490,8 @@ def execute_code(
try:
import shutil
shutil.rmtree(tmpdir, ignore_errors=True)
except Exception:
pass
except Exception as e:
logger.debug("Could not clean temp dir: %s", e)
try:
os.unlink(sock_path)
except OSError:
@ -503,8 +505,8 @@ def _kill_process_group(proc, escalate: bool = False):
except (ProcessLookupError, PermissionError):
try:
proc.kill()
except Exception:
pass
except Exception as e:
logger.debug("Could not kill process: %s", e)
if escalate:
# Give the process 5s to exit after SIGTERM, then SIGKILL
@ -516,8 +518,8 @@ def _kill_process_group(proc, escalate: bool = False):
except (ProcessLookupError, PermissionError):
try:
proc.kill()
except Exception:
pass
except Exception as e:
logger.debug("Could not kill process: %s", e)
def _load_config() -> dict:

View file

@ -277,14 +277,14 @@ class ProcessRegistry:
session.output_buffer += chunk
if len(session.output_buffer) > session.max_output_chars:
session.output_buffer = session.output_buffer[-session.max_output_chars:]
except Exception:
pass
except Exception as e:
logger.debug("Process stdout reader ended: %s", e)
# Process exited
try:
session.process.wait(timeout=5)
except Exception:
pass
except Exception as e:
logger.debug("Process wait timed out or failed: %s", e)
session.exited = True
session.exit_code = session.process.returncode
self._move_to_finished(session)
@ -351,14 +351,14 @@ class ProcessRegistry:
break
except Exception:
break
except Exception:
pass
except Exception as e:
logger.debug("PTY stdout reader ended: %s", e)
# Process exited
try:
pty.wait()
except Exception:
pass
except Exception as e:
logger.debug("PTY wait timed out or failed: %s", e)
session.exited = True
session.exit_code = pty.exitstatus if hasattr(pty, 'exitstatus') else -1
self._move_to_finished(session)
@ -719,8 +719,8 @@ class ProcessRegistry:
# Clear the checkpoint (will be rewritten as processes finish)
try:
CHECKPOINT_PATH.write_text("[]", encoding="utf-8")
except Exception:
pass
except Exception as e:
logger.debug("Could not write checkpoint file: %s", e)
return recovered

View file

@ -154,8 +154,8 @@ class GitHubAuth:
)
if result.returncode == 0 and result.stdout.strip():
return result.stdout.strip()
except (FileNotFoundError, subprocess.TimeoutExpired):
pass
except (FileNotFoundError, subprocess.TimeoutExpired) as e:
logger.debug("gh CLI token lookup failed: %s", e)
return None
def _try_github_app(self) -> Optional[str]:
@ -438,8 +438,8 @@ class GitHubSource(SkillSource):
)
if resp.status_code == 200:
return resp.text
except httpx.HTTPError:
pass
except httpx.HTTPError as e:
logger.debug("GitHub contents API fetch failed: %s", e)
return None
def _read_cache(self, key: str) -> Optional[list]:
@ -461,8 +461,8 @@ class GitHubSource(SkillSource):
cache_file = INDEX_CACHE_DIR / f"{key}.json"
try:
cache_file.write_text(json.dumps(data, ensure_ascii=False))
except OSError:
pass
except OSError as e:
logger.debug("Could not write cache: %s", e)
@staticmethod
def _meta_to_dict(meta: SkillMeta) -> dict:
@ -826,8 +826,8 @@ class LobeHubSource(SkillSource):
resp = httpx.get(url, timeout=15)
if resp.status_code == 200:
return resp.json()
except (httpx.HTTPError, json.JSONDecodeError):
pass
except (httpx.HTTPError, json.JSONDecodeError) as e:
logger.debug("LobeHub agent fetch failed: %s", e)
return None
@staticmethod
@ -890,8 +890,8 @@ def _write_index_cache(key: str, data: Any) -> None:
cache_file = INDEX_CACHE_DIR / f"{key}.json"
try:
cache_file.write_text(json.dumps(data, ensure_ascii=False, default=str))
except OSError:
pass
except OSError as e:
logger.debug("Could not write cache: %s", e)
def _skill_meta_to_dict(meta: SkillMeta) -> dict:
@ -1037,8 +1037,8 @@ def append_audit_log(action: str, skill_name: str, source: str,
try:
with open(AUDIT_LOG, "a") as f:
f.write(line)
except OSError:
pass
except OSError as e:
logger.debug("Could not write audit log: %s", e)
# ---------------------------------------------------------------------------

View file

@ -13,11 +13,14 @@ newline-delimited list of skill names that have been offered to the user.
"""
import json
import logging
import os
import shutil
from pathlib import Path
from typing import List, Tuple
logger = logging.getLogger(__name__)
HERMES_HOME = Path(os.getenv("HERMES_HOME", Path.home() / ".hermes"))
SKILLS_DIR = HERMES_HOME / "skills"
@ -131,8 +134,8 @@ def sync_skills(quiet: bool = False) -> dict:
try:
dest_desc.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(desc_md, dest_desc)
except (OSError, IOError):
pass
except (OSError, IOError) as e:
logger.debug("Could not copy %s: %s", desc_md, e)
_write_manifest(manifest)

View file

@ -122,8 +122,8 @@ def _convert_to_opus(mp3_path: str) -> Optional[str]:
)
if os.path.exists(ogg_path) and os.path.getsize(ogg_path) > 0:
return ogg_path
except Exception:
pass
except Exception as e:
logger.warning("ffmpeg OGG conversion failed: %s", e)
return None