From 28b3f49aaaa69e8cf6225e9d4d35042a4890f777 Mon Sep 17 00:00:00 2001 From: alt-glitch Date: Tue, 21 Apr 2026 12:46:31 +0530 Subject: [PATCH] refactor: remove remaining redundant local imports (comprehensive sweep) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Full AST-based scan of all .py files to find every case where a module or name is imported locally inside a function body but is already available at module level. This is the second pass — the first commit handled the known cases from the lint report; this one catches everything else. Files changed (19): cli.py — 16 removals: time as _time/_t/_tmod (×10), re / re as _re (×2), os as _os, sys, partial os from combo import, from model_tools import get_tool_definitions gateway/run.py — 8 removals: MessageEvent as _ME / MessageType as _MT (×3), os as _os2, MessageEvent+MessageType (×2), Platform, BasePlatformAdapter as _BaseAdapter run_agent.py — 6 removals: get_hermes_home as _ghh, partial (contextlib, os as _os), cleanup_vm, cleanup_browser, set_interrupt as _sif (×2), partial get_toolset_for_tool hermes_cli/main.py — 4 removals: get_hermes_home, time as _time, logging as _log, shutil hermes_cli/config.py — 1 removal: get_hermes_home as _ghome hermes_cli/runtime_provider.py — 1 removal: load_config as _load_bedrock_config hermes_cli/setup.py — 2 removals: importlib.util (×2) hermes_cli/nous_subscription.py — 1 removal: from hermes_cli.config import load_config hermes_cli/tools_config.py — 1 removal: from hermes_cli.config import load_config, save_config cron/scheduler.py — 3 removals: concurrent.futures, json as _json, from hermes_cli.config import load_config batch_runner.py — 1 removal: list_distributions as get_all_dists (kept print_distribution_info, not at top level) tools/send_message_tool.py — 2 removals: import os (×2) tools/skills_tool.py — 1 removal: logging as _logging tools/browser_camofox.py — 1 removal: from hermes_cli.config import load_config tools/image_generation_tool.py — 1 removal: import fal_client environments/tool_context.py — 1 removal: concurrent.futures gateway/platforms/bluebubbles.py — 1 removal: httpx as _httpx gateway/platforms/whatsapp.py — 1 removal: import asyncio tui_gateway/server.py — 2 removals: from datetime import datetime, import time All alias references (_time, _t, _tmod, _re, _os, _os2, _json, _ghh, _ghome, _sif, _ME, _MT, _BaseAdapter, _load_bedrock_config, _httpx, _logging, _log, get_all_dists) updated to use the top-level names. --- batch_runner.py | 8 ++--- cli.py | 53 +++++++++++--------------------- cron/scheduler.py | 5 +-- environments/tool_context.py | 1 - gateway/platforms/bluebubbles.py | 2 +- gateway/platforms/whatsapp.py | 1 - gateway/run.py | 25 +++++---------- hermes_cli/config.py | 3 +- hermes_cli/main.py | 12 +------- hermes_cli/nous_subscription.py | 1 - hermes_cli/runtime_provider.py | 3 +- hermes_cli/setup.py | 2 -- hermes_cli/tools_config.py | 1 - run_agent.py | 17 ++++------ tools/browser_camofox.py | 1 - tools/image_generation_tool.py | 2 +- tools/send_message_tool.py | 2 -- tools/skills_tool.py | 3 +- tui_gateway/server.py | 2 -- 19 files changed, 43 insertions(+), 101 deletions(-) diff --git a/batch_runner.py b/batch_runner.py index c8f275a14..7413ad59f 100644 --- a/batch_runner.py +++ b/batch_runner.py @@ -1190,12 +1190,12 @@ def main( """ # Handle list distributions if list_distributions: - from toolset_distributions import list_distributions as get_all_dists, print_distribution_info - + from toolset_distributions import print_distribution_info + print("📊 Available Toolset Distributions") print("=" * 70) - - all_dists = get_all_dists() + + all_dists = list_distributions() for dist_name in sorted(all_dists.keys()): print_distribution_info(dist_name) diff --git a/cli.py b/cli.py index a045550dd..b5dc6c7c1 100644 --- a/cli.py +++ b/cli.py @@ -7159,7 +7159,6 @@ class HermesCLI: # Refresh the agent's tool list so the model can call new tools if self.agent is not None: - from model_tools import get_tool_definitions self.agent.tools = get_tool_definitions( enabled_toolsets=self.agent.enabled_toolsets if hasattr(self.agent, "enabled_toolsets") else None, @@ -7242,7 +7241,6 @@ class HermesCLI: full history of tool calls (not just the current one in the spinner). """ if event_type == "tool.completed": - import time as _time self._tool_start_time = 0.0 # Print stacked scrollback line for "all" / "new" modes if function_name and self.tool_progress_mode in ("all", "new"): @@ -7271,7 +7269,6 @@ class HermesCLI: if event_type != "tool.started": return if function_name and not function_name.startswith("_"): - import time as _time from agent.display import get_tool_emoji emoji = get_tool_emoji(function_name) label = preview or function_name @@ -7280,7 +7277,7 @@ class HermesCLI: if _pl > 0 and len(label) > _pl: label = label[:_pl - 3] + "..." self._spinner_text = f"{emoji} {label}" - self._tool_start_time = _time.monotonic() + self._tool_start_time = time.monotonic() # Store args for stacked scrollback line on completion self._pending_tool_info.setdefault(function_name, []).append( function_args if function_args is not None else {} @@ -7538,7 +7535,6 @@ class HermesCLI: try: from tools.tts_tool import text_to_speech_tool from tools.voice_mode import play_audio_file - import re # Strip markdown and non-speech content for cleaner TTS tts_text = text[:4000] if len(text) > 4000 else text @@ -8374,8 +8370,7 @@ class HermesCLI: try: _dbg = _hermes_home / "interrupt_debug.log" with open(_dbg, "a") as _f: - import time as _t - _f.write(f"{_t.strftime('%H:%M:%S')} interrupt fired: msg={str(interrupt_msg)[:60]!r}, " + _f.write(f"{time.strftime('%H:%M:%S')} interrupt fired: msg={str(interrupt_msg)[:60]!r}, " f"children={len(self.agent._active_children)}, " f"parent._interrupt={self.agent._interrupt_requested}\n") for _ci, _ch in enumerate(self.agent._active_children): @@ -8451,9 +8446,8 @@ class HermesCLI: # buffer so tool/status lines render ABOVE our response box. # The flush pushes data into the renderer queue; the short # sleep lets the renderer actually paint it before we draw. - import time as _time sys.stdout.flush() - _time.sleep(0.15) + time.sleep(0.15) # Update history with full conversation self.conversation_history = result.get("messages", self.conversation_history) if result else self.conversation_history @@ -9119,8 +9113,7 @@ class HermesCLI: try: _dbg = _hermes_home / "interrupt_debug.log" with open(_dbg, "a") as _f: - import time as _t - _f.write(f"{_t.strftime('%H:%M:%S')} ENTER: queued interrupt msg={str(payload)[:60]!r}, " + _f.write(f"{time.strftime('%H:%M:%S')} ENTER: queued interrupt msg={str(payload)[:60]!r}, " f"agent_running={self._agent_running}\n") except Exception: pass @@ -9268,8 +9261,7 @@ class HermesCLI: 2. Interrupt the running agent (first press) 3. Force exit (second press within 2s, or when idle) """ - import time as _time - now = _time.time() + now = time.time() # Cancel active voice recording. # Run cancel() in a background thread to prevent blocking the @@ -9377,12 +9369,11 @@ class HermesCLI: @kb.add('c-z') def handle_ctrl_z(event): """Handle Ctrl+Z - suspend process to background (Unix only).""" - import sys if sys.platform == 'win32': _cprint(f"\n{_DIM}Suspend (Ctrl+Z) is not supported on Windows.{_RST}") event.app.invalidate() return - import os, signal as _sig + import signal as _sig from prompt_toolkit.application import run_in_terminal from hermes_cli.skin_engine import get_active_skin agent_name = get_active_skin().get_branding("agent_name", "Hermes Agent") @@ -9696,31 +9687,29 @@ class HermesCLI: # extra instructions (sudo countdown, approval navigation, clarify). # The agent-running interrupt hint is now an inline placeholder above. def get_hint_text(): - import time as _time - if cli_ref._sudo_state: - remaining = max(0, int(cli_ref._sudo_deadline - _time.monotonic())) + remaining = max(0, int(cli_ref._sudo_deadline - time.monotonic())) return [ ('class:hint', ' password hidden · Enter to skip'), ('class:clarify-countdown', f' ({remaining}s)'), ] if cli_ref._secret_state: - remaining = max(0, int(cli_ref._secret_deadline - _time.monotonic())) + remaining = max(0, int(cli_ref._secret_deadline - time.monotonic())) return [ ('class:hint', ' secret hidden · Enter to skip'), ('class:clarify-countdown', f' ({remaining}s)'), ] if cli_ref._approval_state: - remaining = max(0, int(cli_ref._approval_deadline - _time.monotonic())) + remaining = max(0, int(cli_ref._approval_deadline - time.monotonic())) return [ ('class:hint', ' ↑/↓ to select, Enter to confirm'), ('class:clarify-countdown', f' ({remaining}s)'), ] if cli_ref._clarify_state: - remaining = max(0, int(cli_ref._clarify_deadline - _time.monotonic())) + remaining = max(0, int(cli_ref._clarify_deadline - time.monotonic())) countdown = f' ({remaining}s)' if cli_ref._clarify_deadline else '' if cli_ref._clarify_freetext: return [ @@ -10268,22 +10257,20 @@ class HermesCLI: app._on_resize = _resize_clear_ghosts def spinner_loop(): - import time as _time - last_idle_refresh = 0.0 while not self._should_exit: if not self._app: - _time.sleep(0.1) + time.sleep(0.1) continue if self._command_running: self._invalidate(min_interval=0.1) - _time.sleep(0.1) + time.sleep(0.1) else: - now = _time.monotonic() + now = time.monotonic() if now - last_idle_refresh >= 1.0: last_idle_refresh = now self._invalidate(min_interval=1.0) - _time.sleep(0.2) + time.sleep(0.2) spinner_thread = threading.Thread(target=spinner_loop, daemon=True) spinner_thread.start() @@ -10352,8 +10339,7 @@ class HermesCLI: continue # Expand paste references back to full content - import re as _re - _paste_ref_re = _re.compile(r'\[Pasted text #\d+: \d+ lines \u2192 (.+?)\]') + _paste_ref_re = re.compile(r'\[Pasted text #\d+: \d+ lines \u2192 (.+?)\]') paste_refs = list(_paste_ref_re.finditer(user_input)) if isinstance(user_input, str) else [] if paste_refs: user_input = self._expand_paste_references(user_input) @@ -10445,13 +10431,12 @@ class HermesCLI: try: if getattr(self, "agent", None) and getattr(self, "_agent_running", False): self.agent.interrupt(f"received signal {signum}") - import time as _t try: _grace = float(os.getenv("HERMES_SIGTERM_GRACE", "1.5")) except (TypeError, ValueError): _grace = 1.5 if _grace > 0: - _t.sleep(_grace) + time.sleep(_grace) except Exception: pass # never block signal handling raise KeyboardInterrupt() @@ -10484,8 +10469,7 @@ class HermesCLI: # uv-managed Python, fd 0 can be invalid or unregisterable with the # asyncio selector, causing "KeyError: '0 is not registered'" (#6393). try: - import os as _os - _os.fstat(0) + os.fstat(0) except OSError: print( "Error: stdin (fd 0) is not available.\n" @@ -10778,13 +10762,12 @@ def main( _agent = getattr(cli, "agent", None) if _agent is not None: _agent.interrupt(f"received signal {signum}") - import time as _t try: _grace = float(os.getenv("HERMES_SIGTERM_GRACE", "1.5")) except (TypeError, ValueError): _grace = 1.5 if _grace > 0: - _t.sleep(_grace) + time.sleep(_grace) except Exception: pass # never block signal handling raise KeyboardInterrupt() diff --git a/cron/scheduler.py b/cron/scheduler.py index 4b131859b..881132006 100644 --- a/cron/scheduler.py +++ b/cron/scheduler.py @@ -422,7 +422,6 @@ def _deliver_result(job: dict, content: str, adapters=None, loop=None) -> Option # prevent "coroutine was never awaited" RuntimeWarning, then retry in a # fresh thread that has no running loop. coro.close() - import concurrent.futures with concurrent.futures.ThreadPoolExecutor(max_workers=1) as pool: future = pool.submit(asyncio.run, _send_to_platform(platform, pconfig, chat_id, cleaned_delivery_content, thread_id=thread_id, media_files=media_files)) result = future.result(timeout=30) @@ -810,14 +809,13 @@ def run_job(job: dict) -> tuple[bool, str, str, Optional[str]]: prefill_messages = None prefill_file = os.getenv("HERMES_PREFILL_MESSAGES_FILE", "") or _cfg.get("prefill_messages_file", "") if prefill_file: - import json as _json pfpath = Path(prefill_file).expanduser() if not pfpath.is_absolute(): pfpath = _hermes_home / pfpath if pfpath.exists(): try: with open(pfpath, "r", encoding="utf-8") as _pf: - prefill_messages = _json.load(_pf) + prefill_messages = json.load(_pf) if not isinstance(prefill_messages, list): prefill_messages = None except Exception as e: @@ -1085,7 +1083,6 @@ def tick(verbose: bool = True, adapters=None, loop=None) -> int: logger.warning("Invalid HERMES_CRON_MAX_PARALLEL value; defaulting to unbounded") if _max_workers is None: try: - from hermes_cli.config import load_config _ucfg = load_config() or {} _cfg_par = ( _ucfg.get("cron", {}) if isinstance(_ucfg, dict) else {} diff --git a/environments/tool_context.py b/environments/tool_context.py index 10f537d72..550c5e851 100644 --- a/environments/tool_context.py +++ b/environments/tool_context.py @@ -53,7 +53,6 @@ def _run_tool_in_thread(tool_name: str, arguments: Dict[str, Any], task_id: str) try: loop = asyncio.get_running_loop() # We're in an async context -- need to run in thread - import concurrent.futures with concurrent.futures.ThreadPoolExecutor(max_workers=1) as pool: future = pool.submit( handle_function_call, tool_name, arguments, task_id diff --git a/gateway/platforms/bluebubbles.py b/gateway/platforms/bluebubbles.py index a8a292969..39d4e537e 100644 --- a/gateway/platforms/bluebubbles.py +++ b/gateway/platforms/bluebubbles.py @@ -75,7 +75,7 @@ def _redact(text: str) -> str: def check_bluebubbles_requirements() -> bool: try: import aiohttp # noqa: F401 - import httpx as _httpx # noqa: F401 + import httpx # noqa: F401 except ImportError: return False return True diff --git a/gateway/platforms/whatsapp.py b/gateway/platforms/whatsapp.py index 767908023..a82417a60 100644 --- a/gateway/platforms/whatsapp.py +++ b/gateway/platforms/whatsapp.py @@ -399,7 +399,6 @@ class WhatsAppAdapter(BasePlatformAdapter): # Check if bridge is already running and connected import aiohttp - import asyncio try: async with aiohttp.ClientSession() as session: async with session.get( diff --git a/gateway/run.py b/gateway/run.py index 647027003..785368cff 100644 --- a/gateway/run.py +++ b/gateway/run.py @@ -3274,10 +3274,9 @@ class GatewayRunner: return "Usage: /queue " adapter = self.adapters.get(source.platform) if adapter: - from gateway.platforms.base import MessageEvent as _ME, MessageType as _MT - queued_event = _ME( + queued_event = MessageEvent( text=queued_text, - message_type=_MT.TEXT, + message_type=MessageType.TEXT, source=event.source, message_id=event.message_id, channel_prompt=event.channel_prompt, @@ -3299,10 +3298,9 @@ class GatewayRunner: # Agent hasn't started yet — queue as turn-boundary fallback. adapter = self.adapters.get(source.platform) if adapter: - from gateway.platforms.base import MessageEvent as _ME, MessageType as _MT - queued_event = _ME( + queued_event = MessageEvent( text=steer_text, - message_type=_MT.TEXT, + message_type=MessageType.TEXT, source=event.source, message_id=event.message_id, channel_prompt=event.channel_prompt, @@ -3322,10 +3320,9 @@ class GatewayRunner: # Running agent is missing or lacks steer() — fall back to queue. adapter = self.adapters.get(source.platform) if adapter: - from gateway.platforms.base import MessageEvent as _ME, MessageType as _MT - queued_event = _ME( + queued_event = MessageEvent( text=steer_text, - message_type=_MT.TEXT, + message_type=MessageType.TEXT, source=event.source, message_id=event.message_id, channel_prompt=event.channel_prompt, @@ -3857,9 +3854,7 @@ class GatewayRunner: for i, path in enumerate(event.media_urls): mtype = event.media_types[i] if i < len(event.media_types) else "" if mtype in ("", "application/octet-stream"): - import os as _os2 - - _ext = _os2.path.splitext(path)[1].lower() + _ext = os.path.splitext(path)[1].lower() if _ext in _TEXT_EXTENSIONS: mtype = "text/plain" else: @@ -8302,7 +8297,6 @@ class GatewayRunner: if not adapter: return try: - from gateway.platforms.base import MessageEvent, MessageType synth_event = MessageEvent( text=synth_text, message_type=MessageType.TEXT, @@ -8407,7 +8401,6 @@ class GatewayRunner: break if adapter and source.chat_id: try: - from gateway.platforms.base import MessageEvent, MessageType synth_event = MessageEvent( text=synth_text, message_type=MessageType.TEXT, @@ -8929,7 +8922,6 @@ class GatewayRunner: if _streaming_enabled: try: from gateway.stream_consumer import GatewayStreamConsumer, StreamConsumerConfig - from gateway.config import Platform _adapter = self.adapters.get(source.platform) if _adapter: _adapter_supports_edit = getattr(_adapter, "SUPPORTS_MESSAGE_EDITING", True) @@ -9279,8 +9271,7 @@ class GatewayRunner: # Skip tool progress for platforms that don't support message # editing (e.g. iMessage/BlueBubbles) — each progress update # would become a separate message bubble, which is noisy. - from gateway.platforms.base import BasePlatformAdapter as _BaseAdapter - if type(adapter).edit_message is _BaseAdapter.edit_message: + if type(adapter).edit_message is BasePlatformAdapter.edit_message: while not progress_queue.empty(): try: progress_queue.get_nowait() diff --git a/hermes_cli/config.py b/hermes_cli/config.py index 255721482..a87d1d23c 100644 --- a/hermes_cli/config.py +++ b/hermes_cli/config.py @@ -2605,8 +2605,7 @@ def migrate_config(interactive: bool = True, quiet: bool = False) -> Dict[str, A # Scan ``$HERMES_HOME/plugins/`` for currently installed user plugins. grandfathered: List[str] = [] try: - from hermes_constants import get_hermes_home as _ghome - user_plugins_dir = _ghome() / "plugins" + user_plugins_dir = get_hermes_home() / "plugins" if user_plugins_dir.is_dir(): for child in sorted(user_plugins_dir.iterdir()): if not child.is_dir(): diff --git a/hermes_cli/main.py b/hermes_cli/main.py index 9fa8f0e52..e9c41f717 100644 --- a/hermes_cli/main.py +++ b/hermes_cli/main.py @@ -4319,8 +4319,6 @@ def _gateway_prompt(prompt_text: str, default: str = "", timeout: float = 300.0) tmp.replace(prompt_path) # Poll for response - import time as _time - deadline = _time.monotonic() + timeout while _time.monotonic() < deadline: if response_path.exists(): @@ -5214,8 +5212,6 @@ def _install_hangup_protection(gateway_mode: bool = False): # (2) Mirror output to update.log and wrap stdio for broken-pipe # tolerance. Any failure here is non-fatal; we just skip the wrap. try: - from hermes_cli.config import get_hermes_home - logs_dir = get_hermes_home() / "logs" logs_dir.mkdir(parents=True, exist_ok=True) log_path = logs_dir / "update.log" @@ -5791,8 +5787,6 @@ def _cmd_update_impl(args, gateway_mode: bool): # Verify the service actually survived the # restart. systemctl restart returns 0 even # if the new process crashes immediately. - import time as _time - _time.sleep(3) verify = subprocess.run( scope_cmd + ["is-active", svc_name], @@ -7679,9 +7673,7 @@ Examples: ) cmd_info["setup_fn"](plugin_parser) except Exception as _exc: - import logging as _log - - _log.getLogger(__name__).debug("Plugin CLI discovery failed: %s", _exc) + logging.getLogger(__name__).debug("Plugin CLI discovery failed: %s", _exc) # ========================================================================= # memory command @@ -8145,8 +8137,6 @@ Examples: # Launch hermes --resume by replacing the current process print(f"Resuming session: {selected_id}") - import shutil - hermes_bin = shutil.which("hermes") if hermes_bin: os.execvp(hermes_bin, ["hermes", "--resume", selected_id]) diff --git a/hermes_cli/nous_subscription.py b/hermes_cli/nous_subscription.py index 691126a4c..a4883b056 100644 --- a/hermes_cli/nous_subscription.py +++ b/hermes_cli/nous_subscription.py @@ -586,7 +586,6 @@ def get_gateway_eligible_tools( return [], [], [] if config is None: - from hermes_cli.config import load_config config = load_config() or {} # Quick provider check without the heavy get_nous_subscription_features call diff --git a/hermes_cli/runtime_provider.py b/hermes_cli/runtime_provider.py index 3b2b4cab3..fd28f5136 100644 --- a/hermes_cli/runtime_provider.py +++ b/hermes_cli/runtime_provider.py @@ -906,8 +906,7 @@ def resolve_runtime_provider( code="no_aws_credentials", ) # Read bedrock-specific config from config.yaml - from hermes_cli.config import load_config as _load_bedrock_config - _bedrock_cfg = _load_bedrock_config().get("bedrock", {}) + _bedrock_cfg = load_config().get("bedrock", {}) # Region priority: config.yaml bedrock.region → env var → us-east-1 region = (_bedrock_cfg.get("region") or "").strip() or resolve_bedrock_region() auth_source = resolve_aws_auth_env_var() or "aws-sdk-default-chain" diff --git a/hermes_cli/setup.py b/hermes_cli/setup.py index 9fcc538c7..3c00fa4f0 100644 --- a/hermes_cli/setup.py +++ b/hermes_cli/setup.py @@ -434,7 +434,6 @@ def _print_setup_summary(config: dict, hermes_home): tool_status.append(("Text-to-Speech (Google Gemini)", True, None)) elif tts_provider == "neutts": try: - import importlib.util neutts_ok = importlib.util.find_spec("neutts") is not None except Exception: neutts_ok = False @@ -963,7 +962,6 @@ def _setup_tts_provider(config: dict): if selected == "neutts": # Check if already installed try: - import importlib.util already_installed = importlib.util.find_spec("neutts") is not None except Exception: already_installed = False diff --git a/hermes_cli/tools_config.py b/hermes_cli/tools_config.py index 23a03b3bd..cb1f39371 100644 --- a/hermes_cli/tools_config.py +++ b/hermes_cli/tools_config.py @@ -1186,7 +1186,6 @@ def _configure_simple_requirements(ts_key: str): if api_key and api_key.strip(): save_env_value("OPENAI_API_KEY", api_key.strip()) # Save vision base URL to config (not .env — only secrets go there) - from hermes_cli.config import load_config, save_config _cfg = load_config() _aux = _cfg.setdefault("auxiliary", {}).setdefault("vision", {}) _aux["base_url"] = base_url diff --git a/run_agent.py b/run_agent.py index e03e285c7..9c6e9d7b9 100644 --- a/run_agent.py +++ b/run_agent.py @@ -1453,11 +1453,10 @@ class AIAgent: if _mp and _mp.is_available(): self._memory_manager.add_provider(_mp) if self._memory_manager.providers: - from hermes_constants import get_hermes_home as _ghh _init_kwargs = { "session_id": self.session_id, "platform": platform or "cli", - "hermes_home": str(_ghh()), + "hermes_home": str(get_hermes_home()), "agent_context": "primary", } # Thread session title for memory provider scoping @@ -2777,10 +2776,10 @@ class AIAgent: prompt = self._SKILL_REVIEW_PROMPT def _run_review(): - import contextlib, os as _os + import contextlib review_agent = None try: - with open(_os.devnull, "w") as _devnull, \ + with open(os.devnull, "w") as _devnull, \ contextlib.redirect_stdout(_devnull), \ contextlib.redirect_stderr(_devnull): review_agent = AIAgent( @@ -3852,14 +3851,12 @@ class AIAgent: # 2. Clean terminal sandbox environments try: - from tools.terminal_tool import cleanup_vm cleanup_vm(task_id) except Exception: pass # 3. Clean browser daemon sessions try: - from tools.browser_tool import cleanup_browser cleanup_browser(task_id) except Exception: pass @@ -7777,8 +7774,7 @@ class AIAgent: # the tool returns True on the next poll. if self._interrupt_requested: try: - from tools.interrupt import set_interrupt as _sif - _sif(True, _worker_tid) + _set_interrupt(True, _worker_tid) except Exception: pass # Set the activity callback on THIS worker thread so @@ -7809,8 +7805,7 @@ class AIAgent: with self._tool_worker_threads_lock: self._tool_worker_threads.discard(_worker_tid) try: - from tools.interrupt import set_interrupt as _sif - _sif(False, _worker_tid) + _set_interrupt(False, _worker_tid) except Exception: pass @@ -11864,7 +11859,7 @@ def main( # Handle tool listing if list_tools: - from model_tools import get_all_tool_names, get_toolset_for_tool, get_available_toolsets + from model_tools import get_all_tool_names, get_available_toolsets from toolsets import get_all_toolsets, get_toolset_info print("📋 Available Tools & Toolsets:") diff --git a/tools/browser_camofox.py b/tools/browser_camofox.py index 0efeb16e9..e1233859a 100644 --- a/tools/browser_camofox.py +++ b/tools/browser_camofox.py @@ -543,7 +543,6 @@ def camofox_vision(question: str, annotate: bool = False, ) try: - from hermes_cli.config import load_config _cfg = load_config() _vision_cfg = _cfg.get("auxiliary", {}).get("vision", {}) _vision_timeout = float(_vision_cfg.get("timeout", 120)) diff --git a/tools/image_generation_tool.py b/tools/image_generation_tool.py index cf1003d12..13f17abe3 100644 --- a/tools/image_generation_tool.py +++ b/tools/image_generation_tool.py @@ -742,7 +742,7 @@ def check_image_generation_requirements() -> bool: try: if not check_fal_api_key(): return False - import fal_client # noqa: F401 — SDK presence check + fal_client # noqa: F401 — SDK presence check return True except ImportError: return False diff --git a/tools/send_message_tool.py b/tools/send_message_tool.py index dacc7e17a..19da4f55a 100644 --- a/tools/send_message_tool.py +++ b/tools/send_message_tool.py @@ -226,7 +226,6 @@ def _handle_send(args): # Weixin can be configured purely via .env; synthesize a pconfig so # send_message and cron delivery work without a gateway.yaml entry. if platform_name == "weixin": - import os wx_token = os.getenv("WEIXIN_TOKEN", "").strip() wx_account = os.getenv("WEIXIN_ACCOUNT_ID", "").strip() if wx_token and wx_account: @@ -254,7 +253,6 @@ def _handle_send(args): if not chat_id: home = config.get_home_channel(platform) if not home and platform_name == "weixin": - import os wx_home = os.getenv("WEIXIN_HOME_CHANNEL", "").strip() if wx_home: from gateway.config import HomeChannel diff --git a/tools/skills_tool.py b/tools/skills_tool.py index f5ab9eeac..dcd1f8c5d 100644 --- a/tools/skills_tool.py +++ b/tools/skills_tool.py @@ -975,8 +975,7 @@ def skill_view(name: str, file_path: str = None, task_id: str = None) -> str: _warnings.append(f"skill file is outside the trusted skills directory (~/.hermes/skills/): {skill_md}") if _injection_detected: _warnings.append("skill content contains patterns that may indicate prompt injection") - import logging as _logging - _logging.getLogger(__name__).warning("Skill security warning for '%s': %s", name, "; ".join(_warnings)) + logging.getLogger(__name__).warning("Skill security warning for '%s': %s", name, "; ".join(_warnings)) parsed_frontmatter: Dict[str, Any] = {} try: diff --git a/tui_gateway/server.py b/tui_gateway/server.py index 6a20b612a..779881780 100644 --- a/tui_gateway/server.py +++ b/tui_gateway/server.py @@ -1608,7 +1608,6 @@ def _(rid, params: dict) -> dict: if err: return err try: - from datetime import datetime from hermes_cli.clipboard import has_clipboard_image, save_clipboard_image except Exception as e: return _err(rid, 5027, f"clipboard unavailable: {e}") @@ -2687,7 +2686,6 @@ def _(rid, params: dict) -> dict: def _(rid, params: dict) -> dict: days = params.get("days", 30) try: - import time cutoff = time.time() - days * 86400 rows = [s for s in _get_db().list_sessions_rich(limit=500) if (s.get("started_at") or 0) >= cutoff] return _ok(rid, {"days": days, "sessions": len(rows), "messages": sum(s.get("message_count", 0) for s in rows)})