From 5b751dc0ad9e7408b20008fea5ec7b29a48afe71 Mon Sep 17 00:00:00 2001 From: teknium1 <127238744+teknium1@users.noreply.github.com> Date: Wed, 29 Jul 2026 09:10:02 -0700 Subject: [PATCH] chore: remove unused imports and dead locals (ruff F401/F841 sweep) Cleans F401 unused imports and F841 dead local assignments across root *.py, agent/, hermes_cli/, tools/, gateway/, cron/, tui_gateway/ (tests/, plugins/, skills/ excluded). Intentionally KEPT (false positives / test-patch surfaces): - agent/transports/__init__.py package re-exports - cli.py browser_connect re-exports (DEFAULT_BROWSER_CDP_URL area, used by tests/cli/test_cli_browser_connect.py) - hermes_cli/main.py _prompt_auth_credentials_choice / _model_flow_bedrock_api_key (accessed via main_mod attr in tests) - gateway/run.py aliased replay_cleanup + whatsapp_identity re-exports and _PORT_BINDING_PLATFORM_VALUES (test-referenced) - hermes_cli/web_server.py get_running_pid (tests monkeypatch it) and _OAUTH_TOKEN_URL availability probe - hermes_cli/config.py get_process_hermes_home re-export (noqa'd F811 chain) and yaml availability-probe import - hermes_cli/nous_subscription.py managed_nous_tools_enabled (tests patch hermes_cli.nous_subscription.managed_nous_tools_enabled) - try/except ImportError availability probes (env_loader, tts_tool, mcp_tool, web_server anthropic OAuth block) - tools/web_tools.py noqa F401 re-exports - hermes_cli/setup_whatsapp_cloud.py:263 'proceed' skipped: possible missing-guard bug, flagged for separate review - unused function parameters (signature changes out of scope) Side-effect RHS calls preserved where only the binding was dead (e.g. web_server proc = _spawn_hermes_action -> bare call). --- agent/billing_usage.py | 2 +- agent/billing_view.py | 2 +- agent/codex_runtime.py | 1 - agent/conversation_loop.py | 3 --- agent/curator.py | 1 - agent/learning_graph_render.py | 1 - agent/lsp/cli.py | 2 +- agent/lsp/install.py | 1 - agent/subagent_lifecycle.py | 2 +- agent/tool_executor.py | 1 - agent/transports/chat_completions.py | 2 -- cli.py | 3 --- cron/executions.py | 2 -- cron/scheduler.py | 1 - gateway/config.py | 1 - gateway/platforms/api_server.py | 3 --- gateway/platforms/base.py | 1 - gateway/platforms/webhook.py | 2 +- gateway/platforms/whatsapp_cloud.py | 1 - gateway/run.py | 14 +------------- gateway/session.py | 2 +- gateway/stream_consumer.py | 1 - hermes_cli/auth.py | 2 +- hermes_cli/cli_billing_mixin.py | 1 - hermes_cli/console_engine.py | 2 +- hermes_cli/dashboard_auth/routes.py | 2 +- hermes_cli/dep_ensure.py | 1 - hermes_cli/doctor.py | 1 - hermes_cli/gateway.py | 2 -- hermes_cli/gateway_enroll.py | 2 +- hermes_cli/kanban.py | 1 - hermes_cli/kanban_db.py | 5 ----- hermes_cli/middleware.py | 2 +- hermes_cli/model_setup_flows.py | 3 --- hermes_cli/model_switch.py | 1 - hermes_cli/nous_subscription.py | 1 - hermes_cli/proxy_cli.py | 1 - hermes_cli/security_audit_startup.py | 2 +- hermes_cli/session_export_html.py | 1 - hermes_cli/setup.py | 10 ---------- hermes_cli/toolset_validation.py | 2 +- hermes_cli/web_server.py | 3 +-- hermes_cli/windows_ssh_runtime.py | 1 - hermes_state.py | 1 - run_agent.py | 2 +- tools/blueprints.py | 1 - tools/close_terminal_tool.py | 1 - tools/computer_use/cua_backend.py | 3 --- tools/computer_use/doctor.py | 1 - tools/delegate_tool.py | 1 - tools/discord_tool.py | 1 - tools/env_probe.py | 1 - tools/read_terminal_tool.py | 1 - tools/send_message_tool.py | 2 -- tools/skill_usage.py | 2 +- tools/skills_hub.py | 2 +- tools/web_tools.py | 1 - tui_gateway/server.py | 1 - 58 files changed, 18 insertions(+), 98 deletions(-) diff --git a/agent/billing_usage.py b/agent/billing_usage.py index 2ac762bc2b3..c3ab6203e30 100644 --- a/agent/billing_usage.py +++ b/agent/billing_usage.py @@ -34,7 +34,7 @@ from __future__ import annotations import logging import math import os -from dataclasses import dataclass, field +from dataclasses import dataclass from typing import Any, Optional logger = logging.getLogger(__name__) diff --git a/agent/billing_view.py b/agent/billing_view.py index 29e8068c227..01a804e65f0 100644 --- a/agent/billing_view.py +++ b/agent/billing_view.py @@ -17,7 +17,7 @@ from __future__ import annotations import logging import os import uuid -from dataclasses import dataclass, field +from dataclasses import dataclass from decimal import Decimal, InvalidOperation from typing import Any, Optional diff --git a/agent/codex_runtime.py b/agent/codex_runtime.py index 0e0b87b2196..7b8bed6137b 100644 --- a/agent/codex_runtime.py +++ b/agent/codex_runtime.py @@ -18,7 +18,6 @@ from __future__ import annotations import json import logging -import os import time from types import SimpleNamespace from typing import Any, Callable, Dict, List diff --git a/agent/conversation_loop.py b/agent/conversation_loop.py index 06504616bac..95c4f7ea925 100644 --- a/agent/conversation_loop.py +++ b/agent/conversation_loop.py @@ -22,9 +22,7 @@ import os import random import re import ssl -import threading import time -import uuid from typing import Any, Dict, List, Optional from agent.codex_responses_adapter import _summarize_user_message_for_log @@ -40,7 +38,6 @@ from agent.conversation_compression import ( from agent.context_engine import automatic_compaction_status_message from agent.display import KawaiiSpinner from agent.error_classifier import FailoverReason, classify_api_error -from agent.iteration_budget import IterationBudget from agent.turn_context import ( _compression_warrants_another_preflight_pass, build_turn_context, diff --git a/agent/curator.py b/agent/curator.py index 975ed102de0..21827bec484 100644 --- a/agent/curator.py +++ b/agent/curator.py @@ -902,7 +902,6 @@ def _reconcile_classification( Every removed skill is placed in exactly one bucket. """ heur_cons = {e["name"]: e for e in heuristic.get("consolidated", [])} - heur_pruned = {e["name"] for e in heuristic.get("pruned", [])} model_cons = {e["from"]: e for e in model_block.get("consolidations", [])} model_pruned = {e["name"]: e for e in model_block.get("prunings", [])} diff --git a/agent/learning_graph_render.py b/agent/learning_graph_render.py index 3602ee270e6..479b2f5b4b7 100644 --- a/agent/learning_graph_render.py +++ b/agent/learning_graph_render.py @@ -403,7 +403,6 @@ def _category_counts(payload: dict[str, Any]) -> list[tuple[str, int]]: def category_color_map(payload: dict[str, Any]) -> dict[str, str]: """Deterministic, evenly-spread hue per skill category (theme-independent).""" clusters = _category_counts(payload) - n = max(1, len(clusters)) # Golden-angle hue spacing so adjacent categories never collide in color. return {cat: rgb_to_hex(_hsl_to_rgb((i * 137.508) % 360, 0.55, 0.62)) for i, (cat, _c) in enumerate(clusters)} diff --git a/agent/lsp/cli.py b/agent/lsp/cli.py index 139baa213f7..607c156d102 100644 --- a/agent/lsp/cli.py +++ b/agent/lsp/cli.py @@ -55,7 +55,7 @@ def register_subparser(subparsers: argparse._SubParsersAction) -> None: help="Even attempt servers marked manual-install (best effort)", ) - sub_restart = sub.add_parser( + sub.add_parser( "restart", help="Tear down running LSP clients (next edit re-spawns)", ) diff --git a/agent/lsp/install.py b/agent/lsp/install.py index c4951854dca..2671e7ccd32 100644 --- a/agent/lsp/install.py +++ b/agent/lsp/install.py @@ -30,7 +30,6 @@ import logging import os import shutil import subprocess -import sys import threading from pathlib import Path from typing import Any, Dict, Optional diff --git a/agent/subagent_lifecycle.py b/agent/subagent_lifecycle.py index b85d84d9e19..bbe63ad0930 100644 --- a/agent/subagent_lifecycle.py +++ b/agent/subagent_lifecycle.py @@ -18,7 +18,7 @@ import secrets import threading import time from contextlib import contextmanager -from concurrent.futures import Future, ThreadPoolExecutor, TimeoutError +from concurrent.futures import Future, TimeoutError from typing import Any, Callable, Mapping, Optional diff --git a/agent/tool_executor.py b/agent/tool_executor.py index 1dfcf1ebf6e..688d5720df2 100644 --- a/agent/tool_executor.py +++ b/agent/tool_executor.py @@ -32,7 +32,6 @@ from agent.display import ( redact_tool_args_for_display as _redact_tool_args_for_display, _detect_tool_failure, ) -from agent.tool_guardrails import ToolGuardrailDecision from agent.tool_dispatch_helpers import ( _is_destructive_command, _is_multimodal_tool_result, diff --git a/agent/transports/chat_completions.py b/agent/transports/chat_completions.py index 086883eca1c..07f76736730 100644 --- a/agent/transports/chat_completions.py +++ b/agent/transports/chat_completions.py @@ -378,7 +378,6 @@ class ChatCompletionsTransport(ProviderTransport): ephemeral = params.get("ephemeral_max_output_tokens") max_tokens = params.get("max_tokens") anthropic_max_out = params.get("anthropic_max_output") - is_nvidia_nim = params.get("is_nvidia_nim", False) is_kimi = params.get("is_kimi", False) is_tokenhub = params.get("is_tokenhub", False) reasoning_config = _reasoning_config_for_model(model, params.get("reasoning_config")) @@ -436,7 +435,6 @@ class ChatCompletionsTransport(ProviderTransport): extra_body: dict[str, Any] = {} is_openrouter = params.get("is_openrouter", False) - is_nous = params.get("is_nous", False) is_github_models = params.get("is_github_models", False) provider_name = str(params.get("provider_name") or "").strip().lower() base_url = params.get("base_url") diff --git a/cli.py b/cli.py index e2044dc1163..33ccf2fa64e 100644 --- a/cli.py +++ b/cli.py @@ -50,8 +50,6 @@ logger = logging.getLogger(__name__) # Suppress startup messages for clean CLI experience os.environ["HERMES_QUIET"] = "1" # Our own modules -import yaml - from hermes_cli.fallback_config import get_fallback_chain from hermes_cli.cli_agent_setup_mixin import CLIAgentSetupMixin from hermes_cli.cli_commands_mixin import CLICommandsMixin @@ -11635,7 +11633,6 @@ class HermesCLI(CLIAgentSetupMixin, CLICommandsMixin, CLIBillingMixin): # it must commit at least the same line. if function_name and self.tool_progress_mode in {"new", "all", "verbose"}: duration = kwargs.get("duration", 0.0) - is_error = kwargs.get("is_error", False) # Pop stored args from tool.started for this function stored = self._pending_tool_info.get(function_name) stored_args = stored.pop(0) if stored else {} diff --git a/cron/executions.py b/cron/executions.py index 4e9b0c7ed78..01437ab9847 100644 --- a/cron/executions.py +++ b/cron/executions.py @@ -7,13 +7,11 @@ proved gone. Terminal states are immutable. from __future__ import annotations -import json import os import sqlite3 import threading import uuid from contextlib import contextmanager -from pathlib import Path from typing import Any, Dict, Iterator, List, Optional from hermes_constants import get_hermes_home diff --git a/cron/scheduler.py b/cron/scheduler.py index e8c0991b81b..77c27727622 100644 --- a/cron/scheduler.py +++ b/cron/scheduler.py @@ -3001,7 +3001,6 @@ def run_job( if prompt is None: logger.info("Job '%s': script produced no output, skipping AI call.", job_name) return True, "", SILENT_MARKER, None - origin = _resolve_origin(job) _cron_session_id = f"cron_{job_id}_{_hermes_now().strftime('%Y%m%d_%H%M%S')}" logger.info("Running job '%s' (ID: %s)", job_name, job_id) diff --git a/gateway/config.py b/gateway/config.py index 759c255bd80..b39ae8cfcb4 100644 --- a/gateway/config.py +++ b/gateway/config.py @@ -2128,7 +2128,6 @@ def _apply_env_overrides(config: GatewayConfig) -> None: ) # API Server - api_server_enabled = is_truthy_value(getenv("API_SERVER_ENABLED", "")) api_server_key = getenv("API_SERVER_KEY", "") api_server_cors_origins = getenv("API_SERVER_CORS_ORIGINS", "") api_server_port = getenv("API_SERVER_PORT") diff --git a/gateway/platforms/api_server.py b/gateway/platforms/api_server.py index 0346fcc2576..e21c2ba4282 100644 --- a/gateway/platforms/api_server.py +++ b/gateway/platforms/api_server.py @@ -3633,21 +3633,18 @@ class APIServerAdapter(BasePlatformAdapter): headers["X-Hermes-Session-Key"] = gateway_session_key response = web.StreamResponse(status=200, headers=headers) await response.prepare(request) - last_write = time.monotonic() try: while True: try: item = await asyncio.wait_for(queue.get(), timeout=CHAT_COMPLETIONS_SSE_KEEPALIVE_SECONDS) except asyncio.TimeoutError: await response.write(b": keepalive\n\n") - last_write = time.monotonic() continue if item is None: break name, payload = item data = json.dumps(payload, ensure_ascii=False) await response.write(f"event: {name}\ndata: {data}\n\n".encode("utf-8")) - last_write = time.monotonic() except (asyncio.CancelledError, ConnectionResetError): task.cancel() raise diff --git a/gateway/platforms/base.py b/gateway/platforms/base.py index f87c3820d6b..0dee81351f1 100644 --- a/gateway/platforms/base.py +++ b/gateway/platforms/base.py @@ -4337,7 +4337,6 @@ class BasePlatformAdapter(ABC): ``MEDIA:`/path/to/file.png` ``) to avoid breaking path extraction. """ chars = list(content) - n = len(chars) # Build list of (start, end) spans to mask spans: list = [] diff --git a/gateway/platforms/webhook.py b/gateway/platforms/webhook.py index 1124666e758..da5eddbe94b 100644 --- a/gateway/platforms/webhook.py +++ b/gateway/platforms/webhook.py @@ -42,7 +42,7 @@ import subprocess import sys import time from collections import deque -from typing import Any, Deque, Dict, List, Optional +from typing import Any, Deque, Dict, Optional try: from aiohttp import web diff --git a/gateway/platforms/whatsapp_cloud.py b/gateway/platforms/whatsapp_cloud.py index 84242adf2c1..074ad1afa2f 100644 --- a/gateway/platforms/whatsapp_cloud.py +++ b/gateway/platforms/whatsapp_cloud.py @@ -76,7 +76,6 @@ from gateway.platforms.base import ( MessageEvent, MessageType, SendResult, - SUPPORTED_DOCUMENT_TYPES, ) from gateway.platforms.whatsapp_common import WhatsAppBehaviorMixin from gateway.platforms.media_cache import ext_for_mime diff --git a/gateway/run.py b/gateway/run.py index ed7825f898c..64d884c63ae 100644 --- a/gateway/run.py +++ b/gateway/run.py @@ -37,23 +37,14 @@ import shlex import site import sys import signal -import tempfile import threading import time -import sqlite3 from collections import OrderedDict from contextvars import copy_context from pathlib import Path from datetime import datetime from typing import Awaitable, Callable, Dict, Optional, Any, List, Union, cast -# account_usage imports the OpenAI SDK chain (~230 ms). Only needed by -# /usage; we still import it at module top in the gateway because test -# patches (tests/gateway/test_usage_command.py) target -# `gateway.run.fetch_account_usage` as a module-level attribute. The -# gateway is a long-running daemon, so its boot cost matters less than -# preserving the established test-patch surface. -from agent.account_usage import fetch_account_usage, render_account_usage_lines from agent.async_utils import consume_detached_task_result, safe_schedule_threadsafe from agent.conversation_compression import ( COMPACTION_STATUS, @@ -407,7 +398,6 @@ def _gateway_loop_exception_handler( """ exc = context.get("exception") if exc is not None and _is_transient_network_error(exc): - message = context.get("message") or "transient network error" task = context.get("future") or context.get("task") task_name = "" if task is not None: @@ -1661,7 +1651,7 @@ sys.path.insert(0, str(Path(__file__).parent.parent)) # Resolve Hermes home directory (respects HERMES_HOME override) from hermes_constants import get_hermes_home, get_hermes_home_override -from utils import atomic_json_write, atomic_yaml_write, base_url_host_matches, is_truthy_value +from utils import atomic_json_write, is_truthy_value _hermes_home = get_hermes_home() # Load environment variables from ~/.hermes/.env first. @@ -2179,7 +2169,6 @@ from gateway.config import ( Platform, _BUILTIN_PLATFORM_VALUES, GatewayConfig, - HomeChannel, PlatformConfig, load_gateway_config, ) @@ -14350,7 +14339,6 @@ class GatewayRunner(GatewayAuthorizationMixin, GatewayKanbanWatchersMixin, Gatew # under that profile's loaded config — check after scope install. if not home_env: try: - from hermes_cli.profiles import get_profile_dir from gateway.config import load_gateway_config as _lgc prof = (getattr(source, "profile", None) or "").strip() if prof and prof != "default": diff --git a/gateway/session.py b/gateway/session.py index 89f4188669e..144de458f71 100644 --- a/gateway/session.py +++ b/gateway/session.py @@ -2956,7 +2956,7 @@ class SessionStore: # Cap pending messages per session to avoid unbounded memory # growth when the DB is persistently broken. Drop the oldest. if len(pending) > self._MAX_PENDING_PER_SESSION: - dropped = pending.pop(0) + pending.pop(0) logger.warning( "Session DB transcript pending queue full for %s " "(cap=%d); dropping oldest message to make room", diff --git a/gateway/stream_consumer.py b/gateway/stream_consumer.py index 7d3e31cf153..b140df2b326 100644 --- a/gateway/stream_consumer.py +++ b/gateway/stream_consumer.py @@ -19,7 +19,6 @@ import asyncio import inspect import logging import queue -import re import threading import time from dataclasses import dataclass diff --git a/hermes_cli/auth.py b/hermes_cli/auth.py index 38fa118f09a..1807d7cf8ec 100644 --- a/hermes_cli/auth.py +++ b/hermes_cli/auth.py @@ -36,7 +36,7 @@ import webbrowser from contextlib import contextmanager from dataclasses import dataclass, field from datetime import datetime, timezone -from http.server import BaseHTTPRequestHandler, HTTPServer, ThreadingHTTPServer +from http.server import BaseHTTPRequestHandler, HTTPServer from pathlib import Path from typing import Any, Callable, Dict, FrozenSet, Iterable, List, Optional, Tuple from urllib.parse import parse_qs, urlencode, urlparse diff --git a/hermes_cli/cli_billing_mixin.py b/hermes_cli/cli_billing_mixin.py index 15e2088a42b..b0ec388a3b4 100644 --- a/hermes_cli/cli_billing_mixin.py +++ b/hermes_cli/cli_billing_mixin.py @@ -15,7 +15,6 @@ Import discipline mirrors ``hermes_cli.cli_commands_mixin``: from __future__ import annotations -import time class CLIBillingMixin: diff --git a/hermes_cli/console_engine.py b/hermes_cli/console_engine.py index 24b258e84e2..4b1eddbaf8c 100644 --- a/hermes_cli/console_engine.py +++ b/hermes_cli/console_engine.py @@ -16,7 +16,7 @@ import io import json import shlex import sys -from dataclasses import dataclass, replace +from dataclasses import dataclass from pathlib import Path from typing import Callable, Iterable, Literal, NoReturn, Sequence diff --git a/hermes_cli/dashboard_auth/routes.py b/hermes_cli/dashboard_auth/routes.py index 58290fddc98..0c142963bcc 100644 --- a/hermes_cli/dashboard_auth/routes.py +++ b/hermes_cli/dashboard_auth/routes.py @@ -19,7 +19,7 @@ import logging import threading import time from collections import defaultdict, deque -from typing import Any, Deque, Dict, Tuple +from typing import Any, Deque, Dict from fastapi import APIRouter, HTTPException, Request from fastapi.responses import HTMLResponse, JSONResponse, RedirectResponse diff --git a/hermes_cli/dep_ensure.py b/hermes_cli/dep_ensure.py index eacb34168bb..3f9cff71cce 100644 --- a/hermes_cli/dep_ensure.py +++ b/hermes_cli/dep_ensure.py @@ -15,7 +15,6 @@ browser tool needs agent-browser). """ from __future__ import annotations -import os import platform import shutil import subprocess diff --git a/hermes_cli/doctor.py b/hermes_cli/doctor.py index 1a673cf02a6..2a6d5b82ac1 100644 --- a/hermes_cli/doctor.py +++ b/hermes_cli/doctor.py @@ -2358,7 +2358,6 @@ def run_doctor(args): [f"Install azure-identity: {sys.executable} -m pip install azure-identity"], ) - base_url = str(model_cfg.get("base_url") or "").strip() entra_cfg = model_cfg.get("entra") or {} if not isinstance(entra_cfg, dict): entra_cfg = {} diff --git a/hermes_cli/gateway.py b/hermes_cli/gateway.py index 2c0bfff2bdc..067b2c3209b 100644 --- a/hermes_cli/gateway.py +++ b/hermes_cli/gateway.py @@ -408,7 +408,6 @@ def _scan_gateway_pids( _no_window = {"creationflags": windows_hide_flags()} wmic_path = shutil.which("wmic") - used_fallback = False result = None if wmic_path is not None: try: @@ -455,7 +454,6 @@ def _scan_gateway_pids( ) except (OSError, subprocess.TimeoutExpired): return [] - used_fallback = True if result.returncode != 0 or result.stdout is None: return [] current_cmd = "" diff --git a/hermes_cli/gateway_enroll.py b/hermes_cli/gateway_enroll.py index 975db9ff80a..d3c56222253 100644 --- a/hermes_cli/gateway_enroll.py +++ b/hermes_cli/gateway_enroll.py @@ -160,7 +160,7 @@ def _post_enroll( def cmd_gateway_enroll(args) -> None: """Enroll this gateway with a relay connector; persist the auth creds to .env.""" - from hermes_cli.auth import AuthError, resolve_nous_access_token + from hermes_cli.auth import AuthError from hermes_cli.config import is_managed, save_env_value # Managed installs get GATEWAY_RELAY_* stamped in by the orchestrator (NAS diff --git a/hermes_cli/kanban.py b/hermes_cli/kanban.py index 2038d151448..a08cb8f9b40 100644 --- a/hermes_cli/kanban.py +++ b/hermes_cli/kanban.py @@ -26,7 +26,6 @@ from typing import Any, Optional from hermes_cli import kanban_db as kb from hermes_cli import kanban_swarm as ks -from hermes_cli.profiles import get_active_profile_name # --------------------------------------------------------------------------- diff --git a/hermes_cli/kanban_db.py b/hermes_cli/kanban_db.py index d32f85f81d3..be9f16f2f27 100644 --- a/hermes_cli/kanban_db.py +++ b/hermes_cli/kanban_db.py @@ -5507,7 +5507,6 @@ def block_task( raise ValueError( f"block kind must be one of {sorted(VALID_BLOCK_KINDS)} or None" ) - routed_to = "blocked" recurrences = 0 with write_txn(conn): cur_row = conn.execute( @@ -5558,7 +5557,6 @@ def block_task( conn, task_id, "dependency_wait", {"reason": reason, "kind": kind}, run_id=run_id, ) - routed_to = "todo" _blocked_task = get_task(conn, task_id) _fire_kanban_lifecycle_hook( "kanban_task_blocked", @@ -5618,7 +5616,6 @@ def block_task( }, run_id=run_id, ) - routed_to = "triage" else: if expected_run_id is None: cur = conn.execute( @@ -7194,7 +7191,6 @@ def detect_stale_running( now = int(time.time()) - host_prefix = f"{_claimer_id().split(':', 1)[0]}:" reclaimed: list[str] = [] rows = conn.execute( @@ -7708,7 +7704,6 @@ def _record_task_failure( if row is None: return False failures = int(row["consecutive_failures"]) + 1 - cur_status = row["status"] # Per-task override wins over both caller-supplied and default # thresholds. None (the common case) falls through. diff --git a/hermes_cli/middleware.py b/hermes_cli/middleware.py index a3b472a4563..e8c00e8200d 100644 --- a/hermes_cli/middleware.py +++ b/hermes_cli/middleware.py @@ -10,7 +10,7 @@ from __future__ import annotations import logging from copy import deepcopy from dataclasses import dataclass, field -from typing import Any, Callable, Dict, List, Optional +from typing import Any, Callable, Dict, List logger = logging.getLogger(__name__) diff --git a/hermes_cli/model_setup_flows.py b/hermes_cli/model_setup_flows.py index fb935de7844..8cefca92469 100644 --- a/hermes_cli/model_setup_flows.py +++ b/hermes_cli/model_setup_flows.py @@ -1981,7 +1981,6 @@ def _model_flow_kimi(config, current_model=""): provider_id = "kimi-coding" pconfig = PROVIDER_REGISTRY[provider_id] - key_env = pconfig.api_key_env_vars[0] if pconfig.api_key_env_vars else "" base_url_env = pconfig.base_url_env_var or "" # Step 1: Check / prompt for API key @@ -2066,7 +2065,6 @@ def _model_flow_stepfun(config, current_model=""): provider_id = "stepfun" pconfig = PROVIDER_REGISTRY[provider_id] - key_env = pconfig.api_key_env_vars[0] if pconfig.api_key_env_vars else "" base_url_env = pconfig.base_url_env_var or "" existing_key, existing_source = _existing_api_key_for_model_flow(provider_id, pconfig) @@ -2174,7 +2172,6 @@ def _model_flow_bedrock_api_key(config, region, current_model=""): from hermes_cli.config import ( load_config, save_config, - get_env_value, save_env_value, ) from hermes_cli.models import _PROVIDER_MODELS diff --git a/hermes_cli/model_switch.py b/hermes_cli/model_switch.py index 80c1ed0e077..e9641fa7b6d 100644 --- a/hermes_cli/model_switch.py +++ b/hermes_cli/model_switch.py @@ -1916,7 +1916,6 @@ def list_authenticated_providers( # --- 1. Check Hermes-mapped providers --- from hermes_cli.models import _AGGREGATOR_PROVIDERS as _AGG_PROVIDERS - from hermes_cli.models import _PROVIDER_ALIASES as _CANON_ALIASES from hermes_cli.providers import ALIASES as _PROVIDER_ALIAS_TABLE for hermes_id, mdev_id in PROVIDER_TO_MODELS_DEV.items(): # Skip vendor names that are merely aliases routing through an diff --git a/hermes_cli/nous_subscription.py b/hermes_cli/nous_subscription.py index bfba9b2dd49..4a05aa84910 100644 --- a/hermes_cli/nous_subscription.py +++ b/hermes_cli/nous_subscription.py @@ -394,7 +394,6 @@ def get_nous_subscription_features( # Per-capability overrides: if set, they determine which backend is active for # search/extract independently of web.backend. web_search_backend = str(web_cfg.get("search_backend") or "").strip().lower() - web_extract_backend = str(web_cfg.get("extract_backend") or "").strip().lower() tts_provider = str(tts_cfg.get("provider") or "edge").strip().lower() # STT default is "local" (faster-whisper) per DEFAULT_CONFIG, which # requires `pip install faster-whisper`. For Nous subscribers we'd diff --git a/hermes_cli/proxy_cli.py b/hermes_cli/proxy_cli.py index 2b90ec90a6c..aab1c6ad3b4 100644 --- a/hermes_cli/proxy_cli.py +++ b/hermes_cli/proxy_cli.py @@ -18,7 +18,6 @@ from __future__ import annotations import argparse import os -from pathlib import Path from typing import List from rich.console import Console diff --git a/hermes_cli/security_audit_startup.py b/hermes_cli/security_audit_startup.py index ca4db54c47e..91e677be311 100644 --- a/hermes_cli/security_audit_startup.py +++ b/hermes_cli/security_audit_startup.py @@ -26,7 +26,7 @@ import logging import os import re from pathlib import Path -from typing import Any, Optional +from typing import Optional logger = logging.getLogger("hermes.security_audit") diff --git a/hermes_cli/session_export_html.py b/hermes_cli/session_export_html.py index 24a5a2bcac0..6c91ed63048 100644 --- a/hermes_cli/session_export_html.py +++ b/hermes_cli/session_export_html.py @@ -6,7 +6,6 @@ No remote dependencies. Enhanced with UI-UX-PRO-MAX design intelligence. """ -import json import datetime import secrets from typing import Any, Dict, List diff --git a/hermes_cli/setup.py b/hermes_cli/setup.py index c5da48c7c32..c4b0c8baf62 100644 --- a/hermes_cli/setup.py +++ b/hermes_cli/setup.py @@ -23,7 +23,6 @@ from typing import Optional, Dict, Any from hermes_cli.nous_subscription import get_nous_subscription_features from tools.tool_backend_helpers import managed_nous_tools_enabled -from utils import base_url_hostname from hermes_constants import get_optional_skills_dir logger = logging.getLogger(__name__) @@ -795,12 +794,6 @@ def setup_model_provider(config: dict, *, quick: bool = False): config.clear() config.update(_refreshed) - # Derive the selected provider for downstream steps (vision setup). - selected_provider = None - _m = config.get("model") - if isinstance(_m, dict): - selected_provider = _m.get("provider") - # Credential rotation, vision-backend selection, and TTS provider are no # longer prompted here. They have safe defaults (rotation off, vision # auto-detected from the main provider, TTS = Edge) and are configurable @@ -880,8 +873,6 @@ def _install_neutts_deps() -> bool: def _install_kittentts_deps() -> bool: """Install KittenTTS dependencies with user approval. Returns True on success.""" - import subprocess - import sys wheel_url = ( "https://github.com/KittenML/KittenTTS/releases/download/" @@ -3177,7 +3168,6 @@ def _run_blank_slate_setup(config: dict, hermes_home, is_existing: bool): Either way nothing is enabled that the user did not explicitly choose. """ - from hermes_cli.config import load_config print() print_header("Blank Slate Setup") diff --git a/hermes_cli/toolset_validation.py b/hermes_cli/toolset_validation.py index cce81407912..4b72ec6be0d 100644 --- a/hermes_cli/toolset_validation.py +++ b/hermes_cli/toolset_validation.py @@ -12,7 +12,7 @@ significant debugging to find. Surfacing invalid toolset names (and the zero-tools end state) loudly turns that silent failure into an actionable one. """ -from typing import Callable, Dict, List +from typing import Callable, List def validate_platform_toolsets( diff --git a/hermes_cli/web_server.py b/hermes_cli/web_server.py index 76e0b002713..1bb2ca96192 100644 --- a/hermes_cli/web_server.py +++ b/hermes_cli/web_server.py @@ -11262,7 +11262,6 @@ def _codex_full_login_worker(session_id: str) -> None: from hermes_cli.auth import ( CODEX_OAUTH_CLIENT_ID, CODEX_OAUTH_TOKEN_URL, - DEFAULT_CODEX_BASE_URL, ) issuer = "https://auth.openai.com" @@ -13410,7 +13409,7 @@ async def install_mcp_catalog_entry(body: MCPCatalogInstall, profile: Optional[s # the first clone is still running. action = _mcp_install_action_name(name) try: - proc = _spawn_hermes_action( + _spawn_hermes_action( _profile_cli_args(effective_profile) + ["mcp", "install", name], action, ) diff --git a/hermes_cli/windows_ssh_runtime.py b/hermes_cli/windows_ssh_runtime.py index 2b58e88918c..427911b73fe 100644 --- a/hermes_cli/windows_ssh_runtime.py +++ b/hermes_cli/windows_ssh_runtime.py @@ -2,7 +2,6 @@ from __future__ import annotations -import argparse import json import os import re diff --git a/hermes_state.py b/hermes_state.py index 97c14ea214f..727edfce683 100644 --- a/hermes_state.py +++ b/hermes_state.py @@ -16,7 +16,6 @@ Key design decisions: import asyncio import atexit -import contextlib import json import logging import os diff --git a/run_agent.py b/run_agent.py index dff990eb83e..641abaf6f6c 100644 --- a/run_agent.py +++ b/run_agent.py @@ -600,7 +600,7 @@ class AIAgent: self._session_db = SessionDB() return self._session_db - except Exception as exc: + except Exception: logger.debug("SessionDB unavailable for recall", exc_info=True) return None diff --git a/tools/blueprints.py b/tools/blueprints.py index 700a17fcd76..58427b7a7f1 100644 --- a/tools/blueprints.py +++ b/tools/blueprints.py @@ -259,7 +259,6 @@ def export_blueprint(job: Dict[str, Any], body: str, *, blueprint_name: Optional name = name.strip("-_") or "shared-blueprint" schedule = job.get("schedule_display") or _schedule_to_string(job.get("schedule")) - skills = job.get("skills") or ([job["skill"]] if job.get("skill") else []) blueprint_block: Dict[str, Any] = {"schedule": schedule} deliver = job.get("deliver") diff --git a/tools/close_terminal_tool.py b/tools/close_terminal_tool.py index 96cc5a22226..b44d3851126 100644 --- a/tools/close_terminal_tool.py +++ b/tools/close_terminal_tool.py @@ -13,7 +13,6 @@ the GUI. """ import json -import os from utils import env_var_enabled diff --git a/tools/computer_use/cua_backend.py b/tools/computer_use/cua_backend.py index c17880537d6..dbc71ab58f8 100644 --- a/tools/computer_use/cua_backend.py +++ b/tools/computer_use/cua_backend.py @@ -2251,9 +2251,6 @@ class CuaDriverBackend(ComputerUseBackend): text = gws_out["data"] if isinstance(gws_out["data"], str) else "" summary, tree = _split_tree_text(text) - # Parse element count from summary e.g. "✅ AppName — 42 elements, turn 3..." - m = re.search(r'(\d+)\s+elements?', summary) - # Surface 2 of NousResearch/hermes-agent#47072: prefer the # canonical structuredContent.elements array (trycua/cua#1961). # Falls back to markdown regex parsing for cua-driver builds diff --git a/tools/computer_use/doctor.py b/tools/computer_use/doctor.py index a69cc3b564f..865a1df0e9a 100644 --- a/tools/computer_use/doctor.py +++ b/tools/computer_use/doctor.py @@ -25,7 +25,6 @@ import json import os import platform as _platform_mod import re -import shutil import subprocess import sys from typing import Any, Dict, List, Optional, Sequence, Tuple diff --git a/tools/delegate_tool.py b/tools/delegate_tool.py index 9d1e9930228..30151b429c4 100644 --- a/tools/delegate_tool.py +++ b/tools/delegate_tool.py @@ -27,7 +27,6 @@ import os import threading import time from concurrent.futures import ( - ThreadPoolExecutor, TimeoutError as FuturesTimeoutError, ) from typing import Any, Dict, List, Optional diff --git a/tools/discord_tool.py b/tools/discord_tool.py index e279f43d5f9..822dfa0c670 100644 --- a/tools/discord_tool.py +++ b/tools/discord_tool.py @@ -172,7 +172,6 @@ _capability_bg_lock = threading.Lock() def _capability_disk_cache_path() -> "Path": - from pathlib import Path from hermes_constants import get_hermes_home diff --git a/tools/env_probe.py b/tools/env_probe.py index 6e28a51cfd2..521ad853d8d 100644 --- a/tools/env_probe.py +++ b/tools/env_probe.py @@ -33,7 +33,6 @@ import logging import os import shutil import subprocess -import sys import tempfile import threading from typing import Optional diff --git a/tools/read_terminal_tool.py b/tools/read_terminal_tool.py index 1c25994e7b7..cfd10e20796 100644 --- a/tools/read_terminal_tool.py +++ b/tools/read_terminal_tool.py @@ -9,7 +9,6 @@ over the platform-injected callback. """ import json -import os from typing import Callable, Optional from tools.registry import registry, tool_error diff --git a/tools/send_message_tool.py b/tools/send_message_tool.py index d1b71a2eb33..4e57dee104c 100644 --- a/tools/send_message_tool.py +++ b/tools/send_message_tool.py @@ -10,9 +10,7 @@ import json import logging import os import re -import ssl import time -from email.utils import formatdate from agent.redact import redact_sensitive_text from agent.secret_scope import get_secret diff --git a/tools/skill_usage.py b/tools/skill_usage.py index 7f519a5d99b..f72894374c7 100644 --- a/tools/skill_usage.py +++ b/tools/skill_usage.py @@ -894,7 +894,7 @@ def archive_skill(skill_name: str) -> Tuple[bool, str]: try: skill_dir.rename(dest) - except OSError as e: + except OSError: # Cross-device — fall back to shutil.move import shutil try: diff --git a/tools/skills_hub.py b/tools/skills_hub.py index f0790d3dbe9..34c12fb3cf4 100644 --- a/tools/skills_hub.py +++ b/tools/skills_hub.py @@ -4031,7 +4031,7 @@ def parallel_search_sources( *on_source_done* is an optional callback ``(source_id, count) -> None`` invoked as each source completes — useful for progress indicators. """ - from concurrent.futures import ThreadPoolExecutor, as_completed + from concurrent.futures import as_completed per_source_limits = per_source_limits or {} diff --git a/tools/web_tools.py b/tools/web_tools.py index 131c0030365..31c425f9a1b 100644 --- a/tools/web_tools.py +++ b/tools/web_tools.py @@ -545,7 +545,6 @@ def _truncate_with_footer( total = len(content) stored_path = _store_full_text(url, content) - shown = len(head) + len(tail) footer_lines = [ "", diff --git a/tui_gateway/server.py b/tui_gateway/server.py index 814fff82445..89ac2cd3a85 100644 --- a/tui_gateway/server.py +++ b/tui_gateway/server.py @@ -1905,7 +1905,6 @@ def _start_agent_build(sid: str, session: dict) -> None: ready.set() return - worker = None notify_registered = False home_token = None secret_token = None