diff --git a/agent/agent_init.py b/agent/agent_init.py index 5897853c0d1..675130a8840 100644 --- a/agent/agent_init.py +++ b/agent/agent_init.py @@ -27,7 +27,6 @@ import threading import time import uuid from datetime import datetime -from pathlib import Path from typing import Any, Dict, List, Optional from urllib.parse import urlparse, parse_qs, urlunparse @@ -37,7 +36,6 @@ from agent.memory_manager import StreamingContextScrubber from agent.model_metadata import ( MINIMUM_CONTEXT_LENGTH, fetch_model_metadata, - get_model_context_length, is_local_endpoint, query_ollama_num_ctx, ) @@ -52,7 +50,6 @@ from agent.tool_guardrails import ( from hermes_cli.config import cfg_get from hermes_cli.timeouts import get_provider_request_timeout from hermes_constants import get_hermes_home -from model_tools import check_toolset_requirements, get_tool_definitions from utils import base_url_host_matches # Use the same logger name as run_agent so tests patching ``run_agent.logger`` @@ -1474,7 +1471,6 @@ def init_agent( # Reject models whose context window is below the minimum required # for reliable tool-calling workflows (64K tokens). - from agent.model_metadata import MINIMUM_CONTEXT_LENGTH _ctx = getattr(agent.context_compressor, "context_length", 0) if _ctx and _ctx < MINIMUM_CONTEXT_LENGTH: raise ValueError( diff --git a/agent/agent_runtime_helpers.py b/agent/agent_runtime_helpers.py index 88775123139..5ce1cc3d291 100644 --- a/agent/agent_runtime_helpers.py +++ b/agent/agent_runtime_helpers.py @@ -25,24 +25,17 @@ from __future__ import annotations import copy import json import logging -import os import re -import threading import time -import uuid from datetime import datetime from pathlib import Path -from typing import Any, Dict, List, Optional, Tuple +from typing import Any, Dict, List, Optional from hermes_cli.timeouts import get_provider_request_timeout -from agent.message_sanitization import ( - _repair_tool_call_arguments, - _sanitize_surrogates, -) from agent.tool_dispatch_helpers import _trajectory_normalize_msg, make_tool_result_message from agent.trajectory import convert_scratchpad_to_think from agent.credential_pool import STATUS_EXHAUSTED -from agent.error_classifier import classify_api_error, FailoverReason +from agent.error_classifier import FailoverReason from utils import base_url_host_matches, base_url_hostname, env_var_enabled, atomic_json_write logger = logging.getLogger(__name__) diff --git a/agent/chat_completion_helpers.py b/agent/chat_completion_helpers.py index 35d0477cf67..3754ff93ff7 100644 --- a/agent/chat_completion_helpers.py +++ b/agent/chat_completion_helpers.py @@ -15,49 +15,23 @@ sites unchanged. Symbols that tests patch on ``run_agent`` (e.g. from __future__ import annotations -import concurrent.futures -import contextvars -import copy import json import logging import os -import random import re -import sys import threading import time import uuid -from datetime import datetime -from pathlib import Path from types import SimpleNamespace -from typing import Any, Dict, List, Optional, Tuple -from urllib.parse import urlparse, parse_qs, urlunparse +from typing import Any, Dict, Optional from hermes_cli.timeouts import get_provider_request_timeout, get_provider_stale_timeout from hermes_constants import PARTIAL_STREAM_STUB_ID, FINISH_REASON_LENGTH -from agent.error_classifier import classify_api_error, FailoverReason +from agent.error_classifier import FailoverReason from agent.model_metadata import is_local_endpoint from agent.message_sanitization import ( _sanitize_surrogates, - _sanitize_messages_surrogates, - _sanitize_structure_surrogates, - _sanitize_messages_non_ascii, - _sanitize_tools_non_ascii, - _sanitize_structure_non_ascii, - _strip_images_from_messages, - _strip_non_ascii, _repair_tool_call_arguments, - _escape_invalid_chars_in_json_strings, -) -from agent.tool_dispatch_helpers import ( - _is_multimodal_tool_result, - _multimodal_text_summary, -) -from agent.retry_utils import jittered_backoff -from agent.tool_guardrails import ( - ToolGuardrailDecision, - append_toolguard_guidance, - toolguard_synthetic_result, ) from tools.terminal_tool import is_persistent_env from utils import base_url_host_matches, base_url_hostname diff --git a/agent/codex_runtime.py b/agent/codex_runtime.py index e2bcbfc824b..398deed3c16 100644 --- a/agent/codex_runtime.py +++ b/agent/codex_runtime.py @@ -16,7 +16,6 @@ compatibility. from __future__ import annotations -import json import logging import os import time diff --git a/agent/conversation_compression.py b/agent/conversation_compression.py index 1ab861bbec9..2ad341fa125 100644 --- a/agent/conversation_compression.py +++ b/agent/conversation_compression.py @@ -34,7 +34,7 @@ import tempfile import uuid from datetime import datetime from pathlib import Path -from typing import Any, List, Optional, Tuple +from typing import Any, Optional, Tuple from agent.model_metadata import estimate_request_tokens_rough diff --git a/agent/conversation_loop.py b/agent/conversation_loop.py index 92796b65c8e..5e49228bc51 100644 --- a/agent/conversation_loop.py +++ b/agent/conversation_loop.py @@ -27,8 +27,6 @@ import time import uuid from typing import Any, Dict, List, Optional -from agent.anthropic_adapter import _is_oauth_token -from agent.auxiliary_client import set_runtime_main from agent.codex_responses_adapter import _summarize_user_message_for_log from agent.display import KawaiiSpinner from agent.error_classifier import FailoverReason, classify_api_error @@ -53,20 +51,13 @@ from agent.model_metadata import ( parse_available_output_tokens_from_error, save_context_length, ) -from agent.nous_rate_guard import ( - clear_nous_rate_limit, - is_genuine_nous_rate_limit, - nous_rate_limit_remaining, - record_nous_rate_limit, -) from agent.process_bootstrap import _install_safe_stdio from agent.prompt_caching import apply_anthropic_cache_control from agent.retry_utils import jittered_backoff from agent.trajectory import has_incomplete_scratchpad from agent.usage_pricing import estimate_usage_cost, normalize_usage -from hermes_constants import display_hermes_home as _dhh_fn, PARTIAL_STREAM_STUB_ID +from hermes_constants import PARTIAL_STREAM_STUB_ID from hermes_logging import set_session_context -from tools.schema_sanitizer import strip_pattern_and_format from tools.skill_provenance import set_current_write_origin from utils import base_url_host_matches, env_var_enabled @@ -409,7 +400,6 @@ def run_conversation( # Tag all log records on this thread with the session ID so # ``hermes logs --session `` can filter a single conversation. - from hermes_logging import set_session_context set_session_context(agent.session_id) # Bind the skill write-origin ContextVar for this thread so tool @@ -418,7 +408,6 @@ def run_conversation( # a foreground user-directed turn. Set at the top of each call; # the review fork runs on its own thread with a fresh context, # so the foreground value here does not leak into it. - from tools.skill_provenance import set_current_write_origin set_current_write_origin(getattr(agent, "_memory_write_origin", "assistant_tool")) # If the previous turn activated fallback, restore the primary diff --git a/agent/credential_pool.py b/agent/credential_pool.py index e62ed59b9b6..feb3cc06b2d 100644 --- a/agent/credential_pool.py +++ b/agent/credential_pool.py @@ -14,7 +14,7 @@ from datetime import datetime, timezone from typing import Any, Dict, List, Optional, Set, Tuple from hermes_constants import OPENROUTER_BASE_URL -from hermes_cli.config import get_env_value, load_env +from hermes_cli.config import load_env from agent.credential_persistence import ( is_borrowed_credential_source, sanitize_borrowed_credential_payload, diff --git a/agent/curator_backup.py b/agent/curator_backup.py index 5e39443bae0..1961b99de3c 100644 --- a/agent/curator_backup.py +++ b/agent/curator_backup.py @@ -39,12 +39,9 @@ from __future__ import annotations import json import logging -import os import re import shutil import tarfile -import tempfile -import time from datetime import datetime, timezone from pathlib import Path from typing import Any, Dict, List, Optional, Tuple diff --git a/agent/google_code_assist.py b/agent/google_code_assist.py index 3e61d1b03e9..eec6441f80e 100644 --- a/agent/google_code_assist.py +++ b/agent/google_code_assist.py @@ -31,7 +31,6 @@ import json import logging import time import urllib.error -import urllib.parse import urllib.request import uuid from dataclasses import dataclass, field diff --git a/agent/lsp/cli.py b/agent/lsp/cli.py index c17ef682b33..121cfa5f92c 100644 --- a/agent/lsp/cli.py +++ b/agent/lsp/cli.py @@ -16,7 +16,6 @@ from __future__ import annotations import argparse import sys -from typing import Optional def register_subparser(subparsers: argparse._SubParsersAction) -> None: @@ -249,7 +248,6 @@ def _cmd_restart() -> int: def _cmd_which(server_id: str) -> int: from agent.lsp.install import INSTALL_RECIPES, hermes_lsp_bin_dir - import os import shutil as _shutil recipe = INSTALL_RECIPES.get(server_id) diff --git a/agent/lsp/manager.py b/agent/lsp/manager.py index 4f16188de0b..aebb4881c96 100644 --- a/agent/lsp/manager.py +++ b/agent/lsp/manager.py @@ -39,25 +39,20 @@ import logging import os import threading import time -from concurrent.futures import Future as ConcurrentFuture from typing import Any, Callable, Dict, List, Optional, Tuple from agent.lsp import eventlog from agent.lsp.client import ( DIAGNOSTICS_DOCUMENT_WAIT, LSPClient, - file_uri, ) from agent.lsp.servers import ( ServerContext, - ServerDef, - SpawnSpec, find_server_for_file, language_id_for, ) from agent.lsp.workspace import ( clear_cache, - is_inside_workspace, resolve_workspace_for_file, ) diff --git a/agent/lsp/servers.py b/agent/lsp/servers.py index 144b5cb2c11..8ba87be9495 100644 --- a/agent/lsp/servers.py +++ b/agent/lsp/servers.py @@ -25,7 +25,7 @@ import shutil from dataclasses import dataclass, field from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple -from agent.lsp.workspace import nearest_root, normalize_path +from agent.lsp.workspace import nearest_root logger = logging.getLogger("agent.lsp.servers") diff --git a/agent/prompt_builder.py b/agent/prompt_builder.py index 059d16ceb1a..8eb0a113ff3 100644 --- a/agent/prompt_builder.py +++ b/agent/prompt_builder.py @@ -7,7 +7,6 @@ assemble pieces, then combines them with memory and ephemeral prompts. import json import logging import os -import re import threading from collections import OrderedDict from pathlib import Path diff --git a/agent/secret_sources/bitwarden.py b/agent/secret_sources/bitwarden.py index 235a4222594..b19451fda22 100644 --- a/agent/secret_sources/bitwarden.py +++ b/agent/secret_sources/bitwarden.py @@ -37,7 +37,6 @@ import platform import shutil import stat import subprocess -import sys import tempfile import time import urllib.error diff --git a/agent/tool_executor.py b/agent/tool_executor.py index 438a6337074..0d27c389595 100644 --- a/agent/tool_executor.py +++ b/agent/tool_executor.py @@ -20,7 +20,7 @@ import os import random import threading import time -from typing import Any, Optional +from typing import Optional from agent.display import ( KawaiiSpinner, diff --git a/agent/transports/chat_completions.py b/agent/transports/chat_completions.py index 0582ef1ef00..259b1b0ca61 100644 --- a/agent/transports/chat_completions.py +++ b/agent/transports/chat_completions.py @@ -10,7 +10,7 @@ reasoning configuration, temperature handling, and extra_body assembly. """ import copy -from typing import Any, Dict, List, Optional +from typing import Any, Dict from agent.lmstudio_reasoning import resolve_lmstudio_effort from agent.moonshot_schema import is_moonshot_model, sanitize_moonshot_tools diff --git a/agent/transports/codex_app_server.py b/agent/transports/codex_app_server.py index 7128de9c4fa..be348a6960f 100644 --- a/agent/transports/codex_app_server.py +++ b/agent/transports/codex_app_server.py @@ -23,7 +23,7 @@ import subprocess import threading import time from dataclasses import dataclass, field -from typing import Any, Callable, Optional +from typing import Any, Optional # Default minimum codex version we test against. The PR sets this from the # `codex --version` parsed at install time; bumping is a one-line change here. diff --git a/gateway/platforms/qqbot/adapter.py b/gateway/platforms/qqbot/adapter.py index 7569884760e..eecf4febfb4 100644 --- a/gateway/platforms/qqbot/adapter.py +++ b/gateway/platforms/qqbot/adapter.py @@ -126,7 +126,6 @@ from gateway.platforms.qqbot.chunked_upload import ( ) from gateway.platforms.qqbot.keyboards import ( ApprovalRequest, - ApprovalSender, InlineKeyboard, InteractionEvent, build_approval_keyboard, diff --git a/gateway/platforms/qqbot/chunked_upload.py b/gateway/platforms/qqbot/chunked_upload.py index 416dfc52a98..6979bd4cb7c 100644 --- a/gateway/platforms/qqbot/chunked_upload.py +++ b/gateway/platforms/qqbot/chunked_upload.py @@ -37,7 +37,7 @@ import asyncio import functools import hashlib import logging -from dataclasses import dataclass, field +from dataclasses import dataclass from pathlib import Path from typing import Any, Awaitable, Callable, Dict, List, Optional diff --git a/gateway/platforms/telegram.py b/gateway/platforms/telegram.py index daaf3fb4d1d..026d8151ceb 100644 --- a/gateway/platforms/telegram.py +++ b/gateway/platforms/telegram.py @@ -1690,7 +1690,6 @@ class TelegramAdapter(BasePlatformAdapter): BotCommandScopeAllPrivateChats, BotCommandScopeAllGroupChats, BotCommandScopeDefault, - BotCommandScopeChat, ) from hermes_cli.commands import telegram_menu_commands # Telegram allows up to 100 commands but has an undocumented diff --git a/gateway/run.py b/gateway/run.py index e30845affa2..f575496e12a 100644 --- a/gateway/run.py +++ b/gateway/run.py @@ -751,7 +751,7 @@ _hermes_home = get_hermes_home() # Load environment variables from ~/.hermes/.env first. # User-managed env files should override stale shell exports on restart. -from dotenv import load_dotenv # backward-compat for tests that monkeypatch this symbol +from dotenv import load_dotenv # noqa: F401 # backward-compat for tests that monkeypatch this symbol from hermes_cli.env_loader import load_hermes_dotenv _env_path = _hermes_home / '.env' load_hermes_dotenv(hermes_home=_hermes_home, project_env=Path(__file__).resolve().parents[1] / '.env') diff --git a/gateway/runtime_footer.py b/gateway/runtime_footer.py index 9d3fea2523b..024cf74d681 100644 --- a/gateway/runtime_footer.py +++ b/gateway/runtime_footer.py @@ -26,7 +26,6 @@ piecemeal, the footer is sent as a separate trailing message via from __future__ import annotations import os -from pathlib import Path from typing import Any, Iterable, Optional _DEFAULT_FIELDS: tuple[str, ...] = ("model", "context_pct", "cwd") diff --git a/hermes_cli/_subprocess_compat.py b/hermes_cli/_subprocess_compat.py index 941728be8ea..4d4ad3f18dc 100644 --- a/hermes_cli/_subprocess_compat.py +++ b/hermes_cli/_subprocess_compat.py @@ -27,11 +27,9 @@ guarantee. from __future__ import annotations -import os import shutil -import subprocess import sys -from typing import Optional, Sequence +from typing import Sequence __all__ = [ "IS_WINDOWS", diff --git a/hermes_cli/auth.py b/hermes_cli/auth.py index 5f0c44f7ed5..e085adae654 100644 --- a/hermes_cli/auth.py +++ b/hermes_cli/auth.py @@ -45,7 +45,6 @@ from typing import Any, Callable, Dict, FrozenSet, List, Optional, Tuple from urllib.parse import parse_qs, urlencode, urlparse import httpx -import yaml from hermes_cli.config import get_hermes_home, get_config_path, read_raw_config from hermes_constants import OPENROUTER_BASE_URL, secure_parent_dir diff --git a/hermes_cli/bundles.py b/hermes_cli/bundles.py index 76f6c7a992e..80f0794c9de 100644 --- a/hermes_cli/bundles.py +++ b/hermes_cli/bundles.py @@ -15,7 +15,7 @@ Subcommands: from __future__ import annotations import sys -from typing import List, Optional +from typing import List from rich.console import Console from rich.table import Table diff --git a/hermes_cli/checkpoints.py b/hermes_cli/checkpoints.py index 2c0d3dd107b..2975553ae49 100644 --- a/hermes_cli/checkpoints.py +++ b/hermes_cli/checkpoints.py @@ -25,7 +25,7 @@ import argparse import time from datetime import datetime from pathlib import Path -from typing import Any, Dict +from typing import Any def _fmt_bytes(n: int) -> str: diff --git a/hermes_cli/debug.py b/hermes_cli/debug.py index b309ee37c54..5556cfc3ae7 100644 --- a/hermes_cli/debug.py +++ b/hermes_cli/debug.py @@ -17,8 +17,6 @@ import logging import re import sys import time -import urllib.error -import urllib.parse import urllib.request from dataclasses import dataclass from pathlib import Path diff --git a/hermes_cli/doctor.py b/hermes_cli/doctor.py index b99eea4d567..3db70beaa72 100644 --- a/hermes_cli/doctor.py +++ b/hermes_cli/doctor.py @@ -8,7 +8,6 @@ import os import sys import subprocess import shutil -import importlib.util from pathlib import Path from hermes_cli.config import get_project_root, get_hermes_home, get_env_path diff --git a/hermes_cli/kanban_db.py b/hermes_cli/kanban_db.py index 26783b4f860..7b5267cc9c3 100644 --- a/hermes_cli/kanban_db.py +++ b/hermes_cli/kanban_db.py @@ -84,7 +84,6 @@ import threading import logging import time from dataclasses import dataclass, field -from datetime import datetime from pathlib import Path from typing import Any, Iterable, Optional @@ -4743,7 +4742,6 @@ def detect_stale_running( if stale_timeout_seconds <= 0: return [] - import signal as _signal_mod now = int(time.time()) host_prefix = f"{_claimer_id().split(':', 1)[0]}:" @@ -6483,7 +6481,7 @@ def _to_epoch(val) -> Optional[int]: pass # ISO-8601 fallback (e.g. '2026-05-10T15:00:00Z') try: - from datetime import datetime, timezone + from datetime import datetime dt = datetime.fromisoformat(s.replace("Z", "+00:00")) return int(dt.timestamp()) except (ValueError, OSError): diff --git a/hermes_cli/main.py b/hermes_cli/main.py index 600b4d4a995..712b740aefe 100644 --- a/hermes_cli/main.py +++ b/hermes_cli/main.py @@ -5593,7 +5593,6 @@ def _model_flow_bedrock(config, current_model=""): def _model_flow_api_key_provider(config, provider_id, current_model=""): """Generic flow for API-key providers (z.ai, MiniMax, OpenCode, etc.).""" from hermes_cli.auth import ( - LMSTUDIO_NOAUTH_PLACEHOLDER, PROVIDER_REGISTRY, _prompt_model_selection, _save_model_choice, diff --git a/hermes_cli/mcp_catalog.py b/hermes_cli/mcp_catalog.py index 18214767590..ba1ab297ed2 100644 --- a/hermes_cli/mcp_catalog.py +++ b/hermes_cli/mcp_catalog.py @@ -23,7 +23,6 @@ See references/mcp-catalog.md (this repo's skill) for the manifest schema. from __future__ import annotations -import os import re import shutil import subprocess @@ -41,7 +40,7 @@ from hermes_cli.config import ( get_env_value, save_env_value, ) -from hermes_cli.cli_output import prompt as _prompt_input, prompt_yes_no +from hermes_cli.cli_output import prompt as _prompt_input _MANIFEST_VERSION = 1 diff --git a/hermes_cli/model_switch.py b/hermes_cli/model_switch.py index b493db5bae6..34c92a365a2 100644 --- a/hermes_cli/model_switch.py +++ b/hermes_cli/model_switch.py @@ -1085,8 +1085,7 @@ def list_authenticated_providers( from hermes_cli.auth import PROVIDER_REGISTRY from hermes_cli.models import ( OPENROUTER_MODELS, _PROVIDER_MODELS, - _MODELS_DEV_PREFERRED, _merge_with_models_dev, provider_model_ids, - cached_provider_model_ids, + _MODELS_DEV_PREFERRED, _merge_with_models_dev, cached_provider_model_ids, get_curated_nous_model_ids, ) diff --git a/hermes_cli/plugins.py b/hermes_cli/plugins.py index 854f3d9f309..b904b8a0125 100644 --- a/hermes_cli/plugins.py +++ b/hermes_cli/plugins.py @@ -34,7 +34,6 @@ so plugin-defined tools appear alongside the built-in tools. from __future__ import annotations import asyncio -import importlib import importlib.metadata import importlib.util import inspect diff --git a/hermes_cli/portal_cli.py b/hermes_cli/portal_cli.py index aa658e41d21..f2631360345 100644 --- a/hermes_cli/portal_cli.py +++ b/hermes_cli/portal_cli.py @@ -13,7 +13,6 @@ from __future__ import annotations import sys import webbrowser -from typing import Optional from hermes_cli.colors import Colors, color from hermes_cli.config import load_config diff --git a/hermes_cli/profile_describer.py b/hermes_cli/profile_describer.py index 0da67e8a3d3..f80d1f5451e 100644 --- a/hermes_cli/profile_describer.py +++ b/hermes_cli/profile_describer.py @@ -28,7 +28,6 @@ from __future__ import annotations import json import logging -import os import re from dataclasses import dataclass from pathlib import Path diff --git a/hermes_cli/profiles.py b/hermes_cli/profiles.py index ec315c7fdb1..b0f1fca4222 100644 --- a/hermes_cli/profiles.py +++ b/hermes_cli/profiles.py @@ -940,7 +940,6 @@ def delete_profile(name: str, yes: bool = False) -> Path: ``sys.exc_info()`` tuple). """ import stat as _stat - import sys as _sys # Normalise the two callback signatures: # onexc(func, path, exc_instance) — 3.12+ diff --git a/hermes_cli/proxy/server.py b/hermes_cli/proxy/server.py index 620f6bbb077..27f8e9e3ff7 100644 --- a/hermes_cli/proxy/server.py +++ b/hermes_cli/proxy/server.py @@ -12,7 +12,6 @@ or rewrite request/response bodies. It's a credential-attaching forwarder. from __future__ import annotations import asyncio -import json import logging import signal from typing import Optional diff --git a/hermes_cli/secrets_cli.py b/hermes_cli/secrets_cli.py index fafb37f576a..5ef8b15aef2 100644 --- a/hermes_cli/secrets_cli.py +++ b/hermes_cli/secrets_cli.py @@ -14,9 +14,8 @@ import argparse import json import os import subprocess -import sys from pathlib import Path -from typing import List, Optional, Tuple +from typing import List, Optional from rich.console import Console from rich.panel import Panel diff --git a/hermes_cli/security_advisories.py b/hermes_cli/security_advisories.py index 311383eab4d..4b83949775c 100644 --- a/hermes_cli/security_advisories.py +++ b/hermes_cli/security_advisories.py @@ -36,7 +36,7 @@ from __future__ import annotations import logging import os import sys -from dataclasses import dataclass, field +from dataclasses import dataclass from pathlib import Path from typing import Iterable, Optional diff --git a/hermes_cli/security_audit.py b/hermes_cli/security_audit.py index 82d414e0b23..f29c61f3332 100644 --- a/hermes_cli/security_audit.py +++ b/hermes_cli/security_audit.py @@ -28,7 +28,7 @@ import urllib.error import urllib.request from dataclasses import dataclass, field from pathlib import Path -from typing import Any, Iterable, Optional +from typing import Iterable, Optional from hermes_constants import get_hermes_home diff --git a/hermes_cli/setup.py b/hermes_cli/setup.py index 61f3eb27460..c9fec686b0e 100644 --- a/hermes_cli/setup.py +++ b/hermes_cli/setup.py @@ -12,7 +12,6 @@ Config files are stored in ~/.hermes/ for easy access. """ import importlib.util -import json import logging import os import re diff --git a/hermes_cli/status.py b/hermes_cli/status.py index 2cce67b9c1d..f1d2f5f9ff7 100644 --- a/hermes_cli/status.py +++ b/hermes_cli/status.py @@ -7,7 +7,6 @@ Shows the status of all Hermes Agent components. import os import sys import subprocess # noqa: F401 — re-exported for tests that monkeypatch status.subprocess to guard against regressions -import importlib.util from pathlib import Path PROJECT_ROOT = Path(__file__).parent.parent.resolve() diff --git a/hermes_cli/stdio.py b/hermes_cli/stdio.py index a1733f0fe0b..b8caf2b052e 100644 --- a/hermes_cli/stdio.py +++ b/hermes_cli/stdio.py @@ -216,7 +216,6 @@ def _augment_path_with_known_tools() -> None: if not is_windows(): return - import shutil as _shutil local_appdata = os.environ.get("LOCALAPPDATA", "") if not local_appdata: diff --git a/hermes_cli/web_server.py b/hermes_cli/web_server.py index d16e2fbcede..eaa1b2432d8 100644 --- a/hermes_cli/web_server.py +++ b/hermes_cli/web_server.py @@ -3351,7 +3351,6 @@ async def get_models_analytics(days: int = 30): # --------------------------------------------------------------------------- import re -import asyncio # PTY bridge is POSIX-only (depends on fcntl/termios/ptyprocess). On native # Windows the import raises; catch and leave PtyBridge=None so the rest of diff --git a/mini_swe_runner.py b/mini_swe_runner.py index e3d2f174e99..95a2cc7285e 100644 --- a/mini_swe_runner.py +++ b/mini_swe_runner.py @@ -29,12 +29,8 @@ Usage: import json import logging import os -import sys -import time -import uuid from datetime import datetime -from pathlib import Path -from typing import List, Dict, Any, Optional, Literal +from typing import List, Dict, Any, Optional import fire from dotenv import load_dotenv diff --git a/optional-skills/creative/meme-generation/scripts/generate_meme.py b/optional-skills/creative/meme-generation/scripts/generate_meme.py index 807fee71165..1a93c13f6b8 100644 --- a/optional-skills/creative/meme-generation/scripts/generate_meme.py +++ b/optional-skills/creative/meme-generation/scripts/generate_meme.py @@ -18,7 +18,6 @@ unknown templates get smart default text positioning based on their box_count. import json import os import sys -import textwrap from io import BytesIO from pathlib import Path diff --git a/optional-skills/finance/dcf-model/scripts/validate_dcf.py b/optional-skills/finance/dcf-model/scripts/validate_dcf.py index 6c8172cf8cf..876edde9f1f 100755 --- a/optional-skills/finance/dcf-model/scripts/validate_dcf.py +++ b/optional-skills/finance/dcf-model/scripts/validate_dcf.py @@ -7,7 +7,6 @@ Validates Excel DCF models for formula errors and common DCF mistakes import sys import json from pathlib import Path -from typing import Optional class DCFModelValidator: diff --git a/optional-skills/health/fitness-nutrition/scripts/nutrition_search.py b/optional-skills/health/fitness-nutrition/scripts/nutrition_search.py index 7494f6c3881..e741fca9abc 100644 --- a/optional-skills/health/fitness-nutrition/scripts/nutrition_search.py +++ b/optional-skills/health/fitness-nutrition/scripts/nutrition_search.py @@ -16,7 +16,6 @@ import json import time import urllib.request import urllib.parse -import urllib.error API_KEY = os.environ.get("USDA_API_KEY", "DEMO_KEY") BASE = "https://api.nal.usda.gov/fdc/v1" diff --git a/optional-skills/research/drug-discovery/scripts/chembl_target.py b/optional-skills/research/drug-discovery/scripts/chembl_target.py index 1346b999ab3..0c7937469ba 100644 --- a/optional-skills/research/drug-discovery/scripts/chembl_target.py +++ b/optional-skills/research/drug-discovery/scripts/chembl_target.py @@ -5,7 +5,7 @@ Usage: python3 chembl_target.py "EGFR" --min-pchembl 7 --limit 20 No external dependencies. """ import sys, json, time, argparse -import urllib.request, urllib.parse, urllib.error +import urllib.request, urllib.parse BASE = "https://www.ebi.ac.uk/chembl/api/data" diff --git a/optional-skills/research/drug-discovery/scripts/ro5_screen.py b/optional-skills/research/drug-discovery/scripts/ro5_screen.py index 84e438fa14b..dd304d0d4d9 100644 --- a/optional-skills/research/drug-discovery/scripts/ro5_screen.py +++ b/optional-skills/research/drug-discovery/scripts/ro5_screen.py @@ -4,8 +4,8 @@ ro5_screen.py — Batch Lipinski Ro5 + Veber screening via PubChem API. Usage: python3 ro5_screen.py aspirin ibuprofen paracetamol No external dependencies beyond stdlib. """ -import sys, json, time, argparse -import urllib.request, urllib.parse, urllib.error +import sys, json, time +import urllib.request, urllib.parse BASE = "https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/name" PROPS = "MolecularWeight,XLogP,HBondDonorCount,HBondAcceptorCount,RotatableBondCount,TPSA" diff --git a/optional-skills/research/osint-investigation/scripts/fetch_gdelt.py b/optional-skills/research/osint-investigation/scripts/fetch_gdelt.py index fa98dabc9bb..008b050ea0d 100644 --- a/optional-skills/research/osint-investigation/scripts/fetch_gdelt.py +++ b/optional-skills/research/osint-investigation/scripts/fetch_gdelt.py @@ -11,7 +11,6 @@ from __future__ import annotations import argparse import csv -import json import sys import time import urllib.parse diff --git a/optional-skills/research/osint-investigation/scripts/fetch_opencorporates.py b/optional-skills/research/osint-investigation/scripts/fetch_opencorporates.py index 6924a8056a6..a30ba13a91e 100644 --- a/optional-skills/research/osint-investigation/scripts/fetch_opencorporates.py +++ b/optional-skills/research/osint-investigation/scripts/fetch_opencorporates.py @@ -12,7 +12,6 @@ from __future__ import annotations import argparse import csv -import json import os import re import sys diff --git a/optional-skills/research/osint-investigation/scripts/fetch_wikipedia.py b/optional-skills/research/osint-investigation/scripts/fetch_wikipedia.py index 4ce5c93813c..3e65b87b882 100644 --- a/optional-skills/research/osint-investigation/scripts/fetch_wikipedia.py +++ b/optional-skills/research/osint-investigation/scripts/fetch_wikipedia.py @@ -12,7 +12,6 @@ from __future__ import annotations import argparse import csv -import json import re import sys import urllib.parse diff --git a/optional-skills/research/osint-investigation/scripts/timing_analysis.py b/optional-skills/research/osint-investigation/scripts/timing_analysis.py index 4e0ece227b4..9407264158d 100644 --- a/optional-skills/research/osint-investigation/scripts/timing_analysis.py +++ b/optional-skills/research/osint-investigation/scripts/timing_analysis.py @@ -19,7 +19,6 @@ import argparse import csv import datetime as dt import json -import math import random import statistics from collections import defaultdict diff --git a/plugins/google_meet/cli.py b/plugins/google_meet/cli.py index 0e9b08881b3..e721c037c81 100644 --- a/plugins/google_meet/cli.py +++ b/plugins/google_meet/cli.py @@ -13,7 +13,6 @@ from __future__ import annotations import argparse import json -import os import sys from pathlib import Path from typing import Optional diff --git a/plugins/platforms/irc/adapter.py b/plugins/platforms/irc/adapter.py index 3358fa5b188..2d06cffbdeb 100644 --- a/plugins/platforms/irc/adapter.py +++ b/plugins/platforms/irc/adapter.py @@ -49,8 +49,7 @@ from gateway.platforms.base import ( MessageEvent, MessageType, ) -from gateway.session import SessionSource -from gateway.config import PlatformConfig, Platform +from gateway.config import Platform # --------------------------------------------------------------------------- diff --git a/plugins/platforms/line/adapter.py b/plugins/platforms/line/adapter.py index ee035ea2e1d..00663702ea1 100644 --- a/plugins/platforms/line/adapter.py +++ b/plugins/platforms/line/adapter.py @@ -76,7 +76,7 @@ import time import uuid from dataclasses import dataclass, field from pathlib import Path -from typing import Any, Awaitable, Callable, Dict, List, Optional, Set, Tuple +from typing import Any, Dict, List, Optional, Set, Tuple from urllib.parse import quote as _urlquote logger = logging.getLogger(__name__) @@ -95,7 +95,6 @@ from gateway.platforms.base import ( cache_image_from_bytes, ) from gateway.config import Platform -from gateway.session import SessionSource # --------------------------------------------------------------------------- diff --git a/plugins/spotify/tools.py b/plugins/spotify/tools.py index f6022ff5aab..4bd18a02b61 100644 --- a/plugins/spotify/tools.py +++ b/plugins/spotify/tools.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Any, Dict, List +from typing import Any, List from hermes_cli.auth import get_auth_status from plugins.spotify.client import ( diff --git a/plugins/teams_pipeline/cli.py b/plugins/teams_pipeline/cli.py index 7afaa3888a0..4b0b1266d94 100644 --- a/plugins/teams_pipeline/cli.py +++ b/plugins/teams_pipeline/cli.py @@ -24,7 +24,6 @@ from plugins.teams_pipeline.store import TeamsPipelineStore, resolve_teams_pipel from plugins.teams_pipeline.subscriptions import ( build_graph_client, maintain_graph_subscriptions, - sync_graph_subscription_record, ) from tools.microsoft_graph_auth import MicrosoftGraphConfigError, MicrosoftGraphTokenProvider diff --git a/plugins/teams_pipeline/pipeline.py b/plugins/teams_pipeline/pipeline.py index d1d16164861..1b2c1d8b0fc 100644 --- a/plugins/teams_pipeline/pipeline.py +++ b/plugins/teams_pipeline/pipeline.py @@ -7,7 +7,6 @@ import json import logging import os import shutil -import subprocess import tempfile import uuid from dataclasses import dataclass @@ -19,7 +18,6 @@ import httpx from agent.auxiliary_client import async_call_llm, extract_content_or_reasoning from hermes_constants import get_hermes_home from plugins.teams_pipeline.meetings import ( - TeamsMeetingArtifactNotFoundError, download_recording_artifact, enrich_meeting_with_call_record, fetch_preferred_transcript_text, diff --git a/run_agent.py b/run_agent.py index a5c9f63e993..f5834867a9c 100644 --- a/run_agent.py +++ b/run_agent.py @@ -33,26 +33,19 @@ except ModuleNotFoundError: import asyncio import base64 -import concurrent.futures -import contextvars import copy import hashlib import json import logging logger = logging.getLogger(__name__) import os -import random import re -import ssl import sys import tempfile import time import threading -from types import SimpleNamespace -import urllib.request import uuid from typing import List, Dict, Any, Optional -from urllib.parse import urlparse, parse_qs, urlunparse # NOTE: `from openai import OpenAI` is deliberately NOT at module top — the # SDK pulls ~240 ms of imports. We expose `OpenAI` as a thin proxy object # that imports the SDK on first call/isinstance check. This preserves: @@ -73,12 +66,6 @@ from hermes_constants import get_hermes_home # OpenAI lazy proxy + safe stdio + proxy URL helpers — see agent/process_bootstrap.py. # `OpenAI` is re-exported here so `patch("run_agent.OpenAI", ...)` in tests works. from agent.process_bootstrap import ( - OpenAI, - _OpenAIProxy, - _load_openai_cls, - _SafeWriter, - _install_safe_stdio, - _get_proxy_from_env, _get_proxy_for_base_url, ) from agent.iteration_budget import IterationBudget @@ -102,77 +89,27 @@ else: # Import our tool system from model_tools import ( - get_tool_definitions, get_toolset_for_tool, - handle_function_call, - check_toolset_requirements, ) -from tools.terminal_tool import cleanup_vm, get_active_env, is_persistent_env -from tools.terminal_tool import ( - set_approval_callback as _set_approval_callback, - set_sudo_password_callback as _set_sudo_password_callback, - _get_approval_callback, - _get_sudo_password_callback, -) -from tools.tool_result_storage import maybe_persist_tool_result, enforce_turn_budget +from tools.terminal_tool import cleanup_vm from tools.interrupt import set_interrupt as _set_interrupt from tools.browser_tool import cleanup_browser # Agent internals extracted to agent/ package for modularity -from agent.memory_manager import StreamingContextScrubber, build_memory_context_block, sanitize_context -from agent.think_scrubber import StreamingThinkScrubber -from agent.retry_utils import jittered_backoff -from agent.error_classifier import classify_api_error, FailoverReason +from agent.memory_manager import sanitize_context +from agent.error_classifier import FailoverReason from agent.redact import redact_sensitive_text -from agent.prompt_builder import ( - DEFAULT_AGENT_IDENTITY, PLATFORM_HINTS, - MEMORY_GUIDANCE, SESSION_SEARCH_GUIDANCE, SKILLS_GUIDANCE, - HERMES_AGENT_HELP_GUIDANCE, - KANBAN_GUIDANCE, - build_nous_subscription_prompt, -) from agent.model_metadata import ( - fetch_model_metadata, - estimate_tokens_rough, estimate_messages_tokens_rough, estimate_request_tokens_rough, - get_next_probe_tier, parse_context_limit_from_error, - parse_available_output_tokens_from_error, - save_context_length, is_local_endpoint, - query_ollama_num_ctx, + is_local_endpoint, ) -from agent.context_compressor import ContextCompressor -from agent.subdirectory_hints import SubdirectoryHintTracker -from agent.prompt_caching import apply_anthropic_cache_control -from agent.prompt_builder import build_skills_system_prompt, build_context_files_prompt, build_environment_hints, load_soul_md, TOOL_USE_ENFORCEMENT_GUIDANCE, TOOL_USE_ENFORCEMENT_MODELS, GOOGLE_MODEL_OPERATIONAL_GUIDANCE, OPENAI_MODEL_EXECUTION_GUIDANCE -from agent.usage_pricing import estimate_usage_cost, normalize_usage -from agent.codex_responses_adapter import ( - _derive_responses_function_call_id as _codex_derive_responses_function_call_id, - _deterministic_call_id as _codex_deterministic_call_id, - _split_responses_tool_id as _codex_split_responses_tool_id, - _summarize_user_message_for_log, -) -from agent.display import ( - KawaiiSpinner, build_tool_preview as _build_tool_preview, - get_cute_tool_message as _get_cute_tool_message_impl, - _detect_tool_failure, - get_tool_emoji as _get_tool_emoji, -) -from agent.tool_guardrails import ( - ToolCallGuardrailConfig, - ToolCallGuardrailController, - ToolGuardrailDecision, - append_toolguard_guidance, - toolguard_synthetic_result, -) -from agent.tool_result_classification import ( - FILE_MUTATING_TOOL_NAMES as _FILE_MUTATING_TOOLS, - file_mutation_result_landed, -) -from agent.trajectory import ( - convert_scratchpad_to_think, - save_trajectory as _save_trajectory_to_file, -) -from agent.message_sanitization import ( +from agent.usage_pricing import normalize_usage +# Re-exported for tests that monkeypatch these symbols on run_agent. +from agent.context_compressor import ContextCompressor # noqa: F401 +from agent.retry_utils import jittered_backoff # noqa: F401 +from agent.prompt_builder import build_skills_system_prompt, load_soul_md # noqa: F401 +from agent.process_bootstrap import _get_proxy_from_env # noqa: F401 +from agent.message_sanitization import ( # noqa: F401 _SURROGATE_RE, _sanitize_surrogates, _sanitize_structure_surrogates, @@ -185,25 +122,33 @@ from agent.message_sanitization import ( _strip_images_from_messages, _sanitize_structure_non_ascii, ) +from agent.codex_responses_adapter import ( + _derive_responses_function_call_id as _codex_derive_responses_function_call_id, + _deterministic_call_id as _codex_deterministic_call_id, + _split_responses_tool_id as _codex_split_responses_tool_id, + _summarize_user_message_for_log, # noqa: F401 # re-exported for tests +) +from agent.tool_guardrails import ( + ToolGuardrailDecision, + append_toolguard_guidance, + toolguard_synthetic_result, +) +from agent.tool_result_classification import ( + FILE_MUTATING_TOOL_NAMES as _FILE_MUTATING_TOOLS, + file_mutation_result_landed, +) +from agent.trajectory import ( + convert_scratchpad_to_think, + save_trajectory as _save_trajectory_to_file, +) from agent.tool_dispatch_helpers import ( - _NEVER_PARALLEL_TOOLS, - _PARALLEL_SAFE_TOOLS, - _PATH_SCOPED_TOOLS, - _DESTRUCTIVE_PATTERNS, - _REDIRECT_OVERWRITE, - _is_destructive_command, _should_parallelize_tool_batch, - _extract_parallel_scope_path, - _paths_overlap, _is_multimodal_tool_result, _multimodal_text_summary, - _append_subdir_hint_to_multimodal, _extract_file_mutation_targets, _extract_error_preview, - _trajectory_normalize_msg, ) -from utils import atomic_json_write, base_url_host_matches, base_url_hostname, env_var_enabled, normalize_proxy_url -from hermes_cli.config import cfg_get +from utils import atomic_json_write, base_url_host_matches, base_url_hostname diff --git a/scripts/contributor_audit.py b/scripts/contributor_audit.py index df2f1d83301..a4166511559 100644 --- a/scripts/contributor_audit.py +++ b/scripts/contributor_audit.py @@ -17,7 +17,6 @@ Usage: import argparse import json -import os import re import subprocess import sys @@ -30,7 +29,7 @@ from pathlib import Path SCRIPT_DIR = Path(__file__).resolve().parent sys.path.insert(0, str(SCRIPT_DIR)) -from release import AUTHOR_MAP, resolve_author # noqa: E402 +from release import resolve_author # noqa: E402 REPO_ROOT = SCRIPT_DIR.parent diff --git a/skills/creative/comfyui/scripts/fetch_logs.py b/skills/creative/comfyui/scripts/fetch_logs.py index e0b6e12ac75..e885a03e70f 100755 --- a/skills/creative/comfyui/scripts/fetch_logs.py +++ b/skills/creative/comfyui/scripts/fetch_logs.py @@ -15,7 +15,6 @@ Usage: from __future__ import annotations import argparse -import json import sys from pathlib import Path diff --git a/skills/creative/comfyui/tests/test_common.py b/skills/creative/comfyui/tests/test_common.py index 0263fe1d91b..a5ce6a32714 100644 --- a/skills/creative/comfyui/tests/test_common.py +++ b/skills/creative/comfyui/tests/test_common.py @@ -2,15 +2,11 @@ from __future__ import annotations -from pathlib import Path import pytest from _common import ( - DEFAULT_LOCAL_HOST, EMBEDDING_REGEX, - FOLDER_ALIASES, - build_cloud_aware_url, cloud_endpoint, coerce_seed, folder_aliases_for, diff --git a/skills/creative/comfyui/tests/test_extract_schema.py b/skills/creative/comfyui/tests/test_extract_schema.py index 072a788f318..c4557ba8caf 100644 --- a/skills/creative/comfyui/tests/test_extract_schema.py +++ b/skills/creative/comfyui/tests/test_extract_schema.py @@ -2,7 +2,6 @@ from __future__ import annotations -import pytest from extract_schema import ( extract_schema, diff --git a/skills/creative/comfyui/tests/test_run_workflow.py b/skills/creative/comfyui/tests/test_run_workflow.py index 32eb172ad1c..69957dd2355 100644 --- a/skills/creative/comfyui/tests/test_run_workflow.py +++ b/skills/creative/comfyui/tests/test_run_workflow.py @@ -2,10 +2,7 @@ from __future__ import annotations -import copy -import json -import pytest from extract_schema import extract_schema from run_workflow import ( diff --git a/skills/productivity/maps/scripts/maps_client.py b/skills/productivity/maps/scripts/maps_client.py index d272b4a7566..90763589ae2 100644 --- a/skills/productivity/maps/scripts/maps_client.py +++ b/skills/productivity/maps/scripts/maps_client.py @@ -18,7 +18,6 @@ Commands: import argparse import json import math -import os import sys import time import urllib.error diff --git a/tests/acp/test_approval_isolation.py b/tests/acp/test_approval_isolation.py index 99a38aadd9e..e6d3f593f76 100644 --- a/tests/acp/test_approval_isolation.py +++ b/tests/acp/test_approval_isolation.py @@ -13,11 +13,8 @@ Both fixed together by: threads don't collide. """ -import os import threading -from unittest.mock import MagicMock -import pytest class TestThreadLocalApprovalCallback: diff --git a/tests/acp/test_events.py b/tests/acp/test_events.py index ec0b32549da..025245ba0a9 100644 --- a/tests/acp/test_events.py +++ b/tests/acp/test_events.py @@ -9,7 +9,7 @@ from unittest.mock import AsyncMock, MagicMock, patch import pytest import acp -from acp.schema import AgentPlanUpdate, ToolCallStart, ToolCallProgress, AgentThoughtChunk, AgentMessageChunk +from acp.schema import AgentPlanUpdate from acp_adapter.events import ( _build_plan_update_from_todo_result, diff --git a/tests/acp/test_mcp_e2e.py b/tests/acp/test_mcp_e2e.py index 00bf53b21f3..f5f62c17a97 100644 --- a/tests/acp/test_mcp_e2e.py +++ b/tests/acp/test_mcp_e2e.py @@ -7,9 +7,6 @@ Exercises the full flow through the ACP server layer: session_update events arrive at the mock client """ -import asyncio -from collections import deque -from types import SimpleNamespace from unittest.mock import AsyncMock, MagicMock, patch import pytest diff --git a/tests/acp/test_server.py b/tests/acp/test_server.py index de9df54d3a6..33fb72c2edc 100644 --- a/tests/acp/test_server.py +++ b/tests/acp/test_server.py @@ -18,7 +18,6 @@ from acp.schema import ( AvailableCommandsUpdate, Implementation, InitializeResponse, - ListSessionsResponse, LoadSessionResponse, NewSessionResponse, PromptResponse, @@ -33,7 +32,6 @@ from acp.schema import ( TextContentBlock, ToolCallProgress, ToolCallStart, - Usage, UsageUpdate, UserMessageChunk, ) diff --git a/tests/acp/test_tools.py b/tests/acp/test_tools.py index 455ee25194a..1da33df1ed4 100644 --- a/tests/acp/test_tools.py +++ b/tests/acp/test_tools.py @@ -1,6 +1,5 @@ """Tests for acp_adapter.tools — tool kind mapping and ACP content building.""" -import pytest from acp_adapter.edit_approval import EditProposal from acp_adapter.tools import ( diff --git a/tests/agent/lsp/test_backend_gate.py b/tests/agent/lsp/test_backend_gate.py index 3c0df8702ea..9d313883d5f 100644 --- a/tests/agent/lsp/test_backend_gate.py +++ b/tests/agent/lsp/test_backend_gate.py @@ -8,8 +8,6 @@ syntax check exactly as if LSP were disabled. """ from __future__ import annotations -import os -import sys from unittest.mock import MagicMock import pytest diff --git a/tests/agent/lsp/test_broken_set.py b/tests/agent/lsp/test_broken_set.py index c854bdc3861..e9f092afb11 100644 --- a/tests/agent/lsp/test_broken_set.py +++ b/tests/agent/lsp/test_broken_set.py @@ -14,15 +14,12 @@ This module verifies: """ from __future__ import annotations -import os -import sys from pathlib import Path -from unittest.mock import MagicMock, patch +from unittest.mock import patch import pytest from agent.lsp.manager import LSPService -from agent.lsp.servers import SERVERS, ServerContext, ServerDef, SpawnSpec from agent.lsp.workspace import clear_cache diff --git a/tests/agent/lsp/test_diagnostics_field.py b/tests/agent/lsp/test_diagnostics_field.py index 6cb0c2896ce..8d5b12aa859 100644 --- a/tests/agent/lsp/test_diagnostics_field.py +++ b/tests/agent/lsp/test_diagnostics_field.py @@ -6,12 +6,8 @@ having LSP output prepended to the lint string. """ from __future__ import annotations -import os -import sys -import tempfile -from unittest.mock import MagicMock, patch +from unittest.mock import patch -import pytest from tools.environments.local import LocalEnvironment from tools.file_operations import ( diff --git a/tests/agent/lsp/test_lifecycle.py b/tests/agent/lsp/test_lifecycle.py index 2fc12b10520..e0f35238fb0 100644 --- a/tests/agent/lsp/test_lifecycle.py +++ b/tests/agent/lsp/test_lifecycle.py @@ -7,7 +7,7 @@ pyright/gopls/etc. are still alive on the host. from __future__ import annotations import atexit -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock import pytest diff --git a/tests/agent/lsp/test_reporter.py b/tests/agent/lsp/test_reporter.py index e4b1cbd39f4..67794e40401 100644 --- a/tests/agent/lsp/test_reporter.py +++ b/tests/agent/lsp/test_reporter.py @@ -2,7 +2,6 @@ from __future__ import annotations from agent.lsp.reporter import ( - DEFAULT_SEVERITIES, MAX_PER_FILE, format_diagnostic, report_for_file, diff --git a/tests/agent/lsp/test_service.py b/tests/agent/lsp/test_service.py index 952a8519adc..24de76e9968 100644 --- a/tests/agent/lsp/test_service.py +++ b/tests/agent/lsp/test_service.py @@ -7,7 +7,6 @@ on. """ from __future__ import annotations -import os import sys from pathlib import Path @@ -19,7 +18,6 @@ from agent.lsp.servers import ( ServerContext, ServerDef, SpawnSpec, - find_server_for_file, ) diff --git a/tests/agent/test_anthropic_keychain.py b/tests/agent/test_anthropic_keychain.py index c0f9c771824..44a458fdf72 100644 --- a/tests/agent/test_anthropic_keychain.py +++ b/tests/agent/test_anthropic_keychain.py @@ -1,10 +1,8 @@ """Tests for Bug #12905 fixes in agent/anthropic_adapter.py — macOS Keychain support.""" import json -import platform from unittest.mock import patch, MagicMock -import pytest from agent.anthropic_adapter import ( _read_claude_code_credentials_from_keychain, diff --git a/tests/agent/test_anthropic_mcp_prefix_strip.py b/tests/agent/test_anthropic_mcp_prefix_strip.py index 102cbadca51..4806661497d 100644 --- a/tests/agent/test_anthropic_mcp_prefix_strip.py +++ b/tests/agent/test_anthropic_mcp_prefix_strip.py @@ -8,11 +8,9 @@ name in the tool registry. from __future__ import annotations -import json from types import SimpleNamespace from unittest.mock import patch -import pytest # --------------------------------------------------------------------------- diff --git a/tests/agent/test_anthropic_oauth_pkce.py b/tests/agent/test_anthropic_oauth_pkce.py index 5cf74d7a6a5..864ee2c700d 100644 --- a/tests/agent/test_anthropic_oauth_pkce.py +++ b/tests/agent/test_anthropic_oauth_pkce.py @@ -15,7 +15,6 @@ History: from __future__ import annotations -import io import json from typing import Any, Dict from urllib.parse import parse_qs, urlparse diff --git a/tests/agent/test_async_utils.py b/tests/agent/test_async_utils.py index 33ce84ee0c6..8354384c34e 100644 --- a/tests/agent/test_async_utils.py +++ b/tests/agent/test_async_utils.py @@ -8,7 +8,6 @@ import warnings from concurrent.futures import Future from unittest.mock import patch -import pytest from agent.async_utils import safe_schedule_threadsafe diff --git a/tests/agent/test_auxiliary_client.py b/tests/agent/test_auxiliary_client.py index 64a9a4a2067..f1f54ae3049 100644 --- a/tests/agent/test_auxiliary_client.py +++ b/tests/agent/test_auxiliary_client.py @@ -2,9 +2,7 @@ import json import logging -import os import time -from pathlib import Path from types import SimpleNamespace from unittest.mock import patch, MagicMock, AsyncMock @@ -609,7 +607,7 @@ class TestExpiredCodexFallback: monkeypatch.setenv("ANTHROPIC_TOKEN", "sk-ant-oat01-test-fallback") with patch("agent.anthropic_adapter.build_anthropic_client") as mock_build: mock_build.return_value = MagicMock() - from agent.auxiliary_client import _resolve_auto, AnthropicAuxiliaryClient + from agent.auxiliary_client import _resolve_auto client, model = _resolve_auto() # Should NOT be Codex, should be Anthropic (or another available provider) assert not isinstance(client, type(None)), "Should find a provider after expired Codex" @@ -696,7 +694,7 @@ class TestExpiredCodexFallback: patch("agent.anthropic_adapter.build_anthropic_client") as mock_build, \ patch("agent.auxiliary_client._select_pool_entry", return_value=(False, None)): mock_build.return_value = MagicMock() - from agent.auxiliary_client import _try_anthropic, AnthropicAuxiliaryClient + from agent.auxiliary_client import _try_anthropic client, model = _try_anthropic() assert client is not None, "Should resolve token" adapter = client.chat.completions @@ -751,7 +749,7 @@ class TestExpiredCodexFallback: monkeypatch.delenv("ANTHROPIC_TOKEN", raising=False) with patch("agent.anthropic_adapter.build_anthropic_client") as mock_build: mock_build.return_value = MagicMock() - from agent.auxiliary_client import _try_anthropic, AnthropicAuxiliaryClient + from agent.auxiliary_client import _try_anthropic client, model = _try_anthropic() assert client is not None adapter = client.chat.completions diff --git a/tests/agent/test_auxiliary_client_azure_foundry.py b/tests/agent/test_auxiliary_client_azure_foundry.py index dea08a5caa2..f3e06e5a513 100644 --- a/tests/agent/test_auxiliary_client_azure_foundry.py +++ b/tests/agent/test_auxiliary_client_azure_foundry.py @@ -27,7 +27,6 @@ from __future__ import annotations import sys from types import SimpleNamespace -from unittest.mock import MagicMock, patch import pytest diff --git a/tests/agent/test_auxiliary_config_bridge.py b/tests/agent/test_auxiliary_config_bridge.py index 3215303b5c2..b2727d33608 100644 --- a/tests/agent/test_auxiliary_config_bridge.py +++ b/tests/agent/test_auxiliary_config_bridge.py @@ -4,14 +4,11 @@ are properly mapped to environment variables by both CLI and gateway loaders. Also tests the vision_tools and browser_tool model override env vars. """ -import json import os import sys from pathlib import Path from unittest.mock import patch, MagicMock -import pytest -import yaml sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..")) diff --git a/tests/agent/test_auxiliary_main_first.py b/tests/agent/test_auxiliary_main_first.py index d1b758c2884..7854313293e 100644 --- a/tests/agent/test_auxiliary_main_first.py +++ b/tests/agent/test_auxiliary_main_first.py @@ -15,7 +15,6 @@ from __future__ import annotations from unittest.mock import MagicMock, patch -import pytest # ── Text aux tasks — _resolve_auto ────────────────────────────────────────── diff --git a/tests/agent/test_auxiliary_named_custom_providers.py b/tests/agent/test_auxiliary_named_custom_providers.py index 52c85998e3d..afceeec02d9 100644 --- a/tests/agent/test_auxiliary_named_custom_providers.py +++ b/tests/agent/test_auxiliary_named_custom_providers.py @@ -1,6 +1,5 @@ """Tests for named custom provider and 'main' alias resolution in auxiliary_client.""" -import os from unittest.mock import patch, MagicMock import pytest diff --git a/tests/agent/test_azure_identity_adapter.py b/tests/agent/test_azure_identity_adapter.py index a569709e00d..c63caf4eace 100644 --- a/tests/agent/test_azure_identity_adapter.py +++ b/tests/agent/test_azure_identity_adapter.py @@ -23,7 +23,6 @@ import sys from collections.abc import Callable from types import SimpleNamespace from typing import cast -from unittest.mock import MagicMock, patch import pytest diff --git a/tests/agent/test_bedrock_adapter.py b/tests/agent/test_bedrock_adapter.py index 04c0913f289..5f98fe5cf78 100644 --- a/tests/agent/test_bedrock_adapter.py +++ b/tests/agent/test_bedrock_adapter.py @@ -10,11 +10,9 @@ Covers: """ import json -import os -import time from contextlib import contextmanager -from types import ModuleType, SimpleNamespace -from unittest.mock import MagicMock, patch, PropertyMock +from types import ModuleType +from unittest.mock import MagicMock, patch import pytest @@ -129,7 +127,7 @@ class TestResolveBedrocRegion: def test_defaults_to_us_east_1(self): from agent.bedrock_adapter import resolve_bedrock_region - from unittest.mock import patch, MagicMock + from unittest.mock import MagicMock mock_session = MagicMock() mock_session.get_config_variable.return_value = None with _mock_botocore_session(return_value=mock_session): @@ -137,7 +135,7 @@ class TestResolveBedrocRegion: def test_falls_back_to_botocore_profile_region(self): from agent.bedrock_adapter import resolve_bedrock_region - from unittest.mock import patch, MagicMock + from unittest.mock import MagicMock mock_session = MagicMock() mock_session.get_config_variable.return_value = "eu-central-1" with _mock_botocore_session(return_value=mock_session): @@ -145,7 +143,6 @@ class TestResolveBedrocRegion: def test_botocore_failure_falls_back_to_us_east_1(self): from agent.bedrock_adapter import resolve_bedrock_region - from unittest.mock import patch with _mock_botocore_session(side_effect=Exception("no botocore")): assert resolve_bedrock_region({}) == "us-east-1" diff --git a/tests/agent/test_bedrock_integration.py b/tests/agent/test_bedrock_integration.py index a5ab3563381..65df149e528 100644 --- a/tests/agent/test_bedrock_integration.py +++ b/tests/agent/test_bedrock_integration.py @@ -9,7 +9,6 @@ Note: Tests that import ``hermes_cli.auth`` or ``hermes_cli.runtime_provider`` require Python 3.10+ due to ``str | None`` type syntax in the import chain. """ -import os from unittest.mock import MagicMock, patch import pytest @@ -93,7 +92,6 @@ class TestResolveProvider: def test_explicit_bedrock_resolves(self, monkeypatch): """When user explicitly requests 'bedrock', it should resolve.""" - from hermes_cli.auth import PROVIDER_REGISTRY # bedrock is in the registry, so resolve_provider should return it from hermes_cli.auth import resolve_provider result = resolve_provider("bedrock") diff --git a/tests/agent/test_codex_cloudflare_headers.py b/tests/agent/test_codex_cloudflare_headers.py index 2d9633a8039..fc52b78e886 100644 --- a/tests/agent/test_codex_cloudflare_headers.py +++ b/tests/agent/test_codex_cloudflare_headers.py @@ -29,7 +29,6 @@ import base64 import json from unittest.mock import MagicMock, patch -import pytest # --------------------------------------------------------------------------- diff --git a/tests/agent/test_compressor_image_tokens.py b/tests/agent/test_compressor_image_tokens.py index 83198e5de90..73492eb8061 100644 --- a/tests/agent/test_compressor_image_tokens.py +++ b/tests/agent/test_compressor_image_tokens.py @@ -8,7 +8,6 @@ creative workflows that iterate on images across many turns. from __future__ import annotations -import pytest from agent.context_compressor import ( _CHARS_PER_TOKEN, diff --git a/tests/agent/test_context_engine.py b/tests/agent/test_context_engine.py index a06285dc2af..32acec010c8 100644 --- a/tests/agent/test_context_engine.py +++ b/tests/agent/test_context_engine.py @@ -232,7 +232,7 @@ class TestPluginContextEngineSlot: assert mgr._context_engine is None def test_get_plugin_context_engine(self): - from hermes_cli.plugins import PluginManager, PluginContext, PluginManifest, get_plugin_context_engine, _plugin_manager + from hermes_cli.plugins import PluginManager, get_plugin_context_engine import hermes_cli.plugins as plugins_mod # Inject a test manager diff --git a/tests/agent/test_context_engine_host_contract.py b/tests/agent/test_context_engine_host_contract.py index 6ab1a22261c..bb6fb4c4108 100644 --- a/tests/agent/test_context_engine_host_contract.py +++ b/tests/agent/test_context_engine_host_contract.py @@ -28,7 +28,6 @@ from __future__ import annotations from unittest.mock import MagicMock -import pytest from run_agent import AIAgent diff --git a/tests/agent/test_crossloop_client_cache.py b/tests/agent/test_crossloop_client_cache.py index be8d51cea8c..364c94e83d0 100644 --- a/tests/agent/test_crossloop_client_cache.py +++ b/tests/agent/test_crossloop_client_cache.py @@ -10,9 +10,7 @@ so it can run without optional dependencies like firecrawl. import asyncio import threading -from concurrent.futures import ThreadPoolExecutor from unittest.mock import patch, MagicMock -from types import SimpleNamespace import pytest @@ -32,7 +30,6 @@ def _stub_resolve_provider_client(provider, model, async_mode, **kw): @pytest.fixture(autouse=True) def _clean_client_cache(): """Clear the client cache before each test.""" - import importlib # We need to patch before importing with patch.dict("sys.modules", {}): pass @@ -48,7 +45,7 @@ class TestCrossLoopCacheIsolation: def test_same_loop_reuses_client(self): """Within a single event loop, the same client should be returned.""" - from agent.auxiliary_client import _get_cached_client, _client_cache + from agent.auxiliary_client import _get_cached_client loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) diff --git a/tests/agent/test_curator.py b/tests/agent/test_curator.py index b564d9f9a08..764f714897e 100644 --- a/tests/agent/test_curator.py +++ b/tests/agent/test_curator.py @@ -7,7 +7,6 @@ tests run fully offline and the curator module doesn't need real credentials. from __future__ import annotations import importlib -import json from datetime import datetime, timedelta, timezone from pathlib import Path diff --git a/tests/agent/test_curator_reports.py b/tests/agent/test_curator_reports.py index 29896a950fd..20773ad9a2f 100644 --- a/tests/agent/test_curator_reports.py +++ b/tests/agent/test_curator_reports.py @@ -7,8 +7,7 @@ the standard log dir, not inside the user's ``skills/`` data directory. from __future__ import annotations import json -import os -from datetime import datetime, timezone, timedelta +from datetime import datetime, timezone from pathlib import Path import pytest diff --git a/tests/agent/test_display.py b/tests/agent/test_display.py index 5e18fa17e0c..994aae28648 100644 --- a/tests/agent/test_display.py +++ b/tests/agent/test_display.py @@ -1,9 +1,8 @@ """Tests for agent/display.py — build_tool_preview() and inline diff previews.""" -import os import json import pytest -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock from agent.display import ( build_tool_preview, diff --git a/tests/agent/test_display_todo_progress.py b/tests/agent/test_display_todo_progress.py index 7205602e01a..d3d804ce14f 100644 --- a/tests/agent/test_display_todo_progress.py +++ b/tests/agent/test_display_todo_progress.py @@ -5,7 +5,6 @@ todo tool call paths: read, create (merge=False), update (merge=True). """ import json -import pytest from agent.display import get_cute_tool_message diff --git a/tests/agent/test_display_tool_failure.py b/tests/agent/test_display_tool_failure.py index ca56e20f3a1..74535831d78 100644 --- a/tests/agent/test_display_tool_failure.py +++ b/tests/agent/test_display_tool_failure.py @@ -7,7 +7,6 @@ not a generic "[error]". """ import json -import pytest from agent.display import ( _detect_tool_failure, diff --git a/tests/agent/test_external_skills.py b/tests/agent/test_external_skills.py index 1a9cd63d580..e49aa5e3962 100644 --- a/tests/agent/test_external_skills.py +++ b/tests/agent/test_external_skills.py @@ -2,7 +2,6 @@ import json import os -from pathlib import Path from unittest.mock import patch import pytest diff --git a/tests/agent/test_external_skills_dirs_cache.py b/tests/agent/test_external_skills_dirs_cache.py index 277214bd0d0..8baf3de4702 100644 --- a/tests/agent/test_external_skills_dirs_cache.py +++ b/tests/agent/test_external_skills_dirs_cache.py @@ -11,7 +11,6 @@ cache invalidates when config.yaml's mtime changes. from __future__ import annotations import os -import time from pathlib import Path from unittest.mock import patch diff --git a/tests/agent/test_file_safety.py b/tests/agent/test_file_safety.py index a7ff019d438..b0303d561f9 100644 --- a/tests/agent/test_file_safety.py +++ b/tests/agent/test_file_safety.py @@ -4,8 +4,6 @@ Run with: python -m pytest tests/agent/test_file_safety.py -v """ import os -import tempfile -from pathlib import Path from unittest.mock import patch import pytest diff --git a/tests/agent/test_file_safety_cross_profile.py b/tests/agent/test_file_safety_cross_profile.py index cf3605774a3..d9d42bc5409 100644 --- a/tests/agent/test_file_safety_cross_profile.py +++ b/tests/agent/test_file_safety_cross_profile.py @@ -12,7 +12,6 @@ afterwards that the second path belonged to a different profile. """ from __future__ import annotations -import os from pathlib import Path import pytest diff --git a/tests/agent/test_gemini_cloudcode.py b/tests/agent/test_gemini_cloudcode.py index 480f562aa64..600a06ffe93 100644 --- a/tests/agent/test_gemini_cloudcode.py +++ b/tests/agent/test_gemini_cloudcode.py @@ -18,8 +18,6 @@ import json import stat import time from pathlib import Path -from types import SimpleNamespace -from unittest.mock import MagicMock, patch import pytest diff --git a/tests/agent/test_gemini_free_tier_gate.py b/tests/agent/test_gemini_free_tier_gate.py index bbd74389f53..f2d47653472 100644 --- a/tests/agent/test_gemini_free_tier_gate.py +++ b/tests/agent/test_gemini_free_tier_gate.py @@ -3,7 +3,6 @@ from __future__ import annotations from unittest.mock import MagicMock, patch -import pytest from agent.gemini_native_adapter import ( gemini_http_error, diff --git a/tests/agent/test_image_routing.py b/tests/agent/test_image_routing.py index 4ec5986ce77..b5a43f1ff0e 100644 --- a/tests/agent/test_image_routing.py +++ b/tests/agent/test_image_routing.py @@ -6,7 +6,6 @@ import base64 from pathlib import Path from unittest.mock import patch -import pytest from agent.image_routing import ( _coerce_capability_bool, diff --git a/tests/agent/test_insights.py b/tests/agent/test_insights.py index 2740daf0962..723a40da4fb 100644 --- a/tests/agent/test_insights.py +++ b/tests/agent/test_insights.py @@ -2,7 +2,6 @@ import time import pytest -from pathlib import Path from hermes_state import SessionDB from agent.insights import ( @@ -11,7 +10,6 @@ from agent.insights import ( _format_duration, _bar_chart, _has_known_pricing, - _DEFAULT_PRICING, ) @@ -596,7 +594,6 @@ class TestEdgeCases: def test_tool_usage_from_tool_calls_json(self, db): """Tool usage should be extracted from tool_calls JSON when tool_name is NULL.""" - import json as _json db.create_session(session_id="s1", source="cli", model="test") # Assistant message with tool_calls (this is what CLI produces) db.append_message("s1", role="assistant", content="Let me search", diff --git a/tests/agent/test_memory_provider.py b/tests/agent/test_memory_provider.py index 3c54f78d5be..c516e408f7c 100644 --- a/tests/agent/test_memory_provider.py +++ b/tests/agent/test_memory_provider.py @@ -2,7 +2,7 @@ import json import pytest -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock from agent.memory_provider import MemoryProvider from agent.memory_manager import MemoryManager @@ -462,7 +462,7 @@ class TestUserInstalledProviderDiscovery: def test_discover_finds_user_plugins(self, tmp_path, monkeypatch): """discover_memory_providers() includes user-installed plugins.""" - from plugins.memory import discover_memory_providers, _get_user_plugins_dir + from plugins.memory import discover_memory_providers self._make_user_memory_plugin(tmp_path, "myexternal") monkeypatch.setattr( "plugins.memory._get_user_plugins_dir", diff --git a/tests/agent/test_memory_session_switch.py b/tests/agent/test_memory_session_switch.py index 61cd6edbafd..a40654fa579 100644 --- a/tests/agent/test_memory_session_switch.py +++ b/tests/agent/test_memory_session_switch.py @@ -7,7 +7,6 @@ state in initialize() (Hindsight, and any plugin that stores session_id for scoped writes) keep writing into the old session's record. """ -import json import pytest diff --git a/tests/agent/test_memory_user_id.py b/tests/agent/test_memory_user_id.py index 7b60b05dd24..2692dcb191d 100644 --- a/tests/agent/test_memory_user_id.py +++ b/tests/agent/test_memory_user_id.py @@ -6,7 +6,6 @@ so each gateway user gets their own memory bucket instead of sharing a static on import json import os -import pytest from unittest.mock import MagicMock, patch from agent.memory_provider import MemoryProvider diff --git a/tests/agent/test_model_metadata.py b/tests/agent/test_model_metadata.py index 20a4bacaad6..3f9fd56d140 100644 --- a/tests/agent/test_model_metadata.py +++ b/tests/agent/test_model_metadata.py @@ -10,13 +10,9 @@ Coverage levels: Persistent cache — save/load, corruption, update, provider isolation """ -import os import time -import tempfile -import pytest import yaml -from pathlib import Path from unittest.mock import patch, MagicMock from agent.model_metadata import ( diff --git a/tests/agent/test_model_metadata_local_ctx.py b/tests/agent/test_model_metadata_local_ctx.py index f449255c073..ca1c5d3f94a 100644 --- a/tests/agent/test_model_metadata_local_ctx.py +++ b/tests/agent/test_model_metadata_local_ctx.py @@ -6,12 +6,10 @@ All tests use synthetic inputs — no filesystem or live server required. import sys import os -import json from unittest.mock import MagicMock, patch sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) -import pytest # --------------------------------------------------------------------------- @@ -562,7 +560,7 @@ class TestGetModelContextLengthLocalFallback: def test_non_local_endpoint_does_not_query_local_server(self): """For non-local endpoints, _query_local_context_length is not called.""" - from agent.model_metadata import get_model_context_length, CONTEXT_PROBE_TIERS + from agent.model_metadata import get_model_context_length with patch("agent.model_metadata.get_cached_context_length", return_value=None), \ patch("agent.model_metadata.fetch_endpoint_model_metadata", return_value={}), \ diff --git a/tests/agent/test_models_dev.py b/tests/agent/test_models_dev.py index 0353feba1de..41fb4463ec8 100644 --- a/tests/agent/test_models_dev.py +++ b/tests/agent/test_models_dev.py @@ -1,8 +1,6 @@ """Tests for agent.models_dev — models.dev registry integration.""" -import json from unittest.mock import patch, MagicMock -import pytest from agent.models_dev import ( PROVIDER_TO_MODELS_DEV, _extract_context, diff --git a/tests/agent/test_non_stream_stale_timeout.py b/tests/agent/test_non_stream_stale_timeout.py index 702856275f6..281453db16d 100644 --- a/tests/agent/test_non_stream_stale_timeout.py +++ b/tests/agent/test_non_stream_stale_timeout.py @@ -11,10 +11,8 @@ Covers: from __future__ import annotations -import os from pathlib import Path -import pytest def _write_config(tmp_path: Path, body: str) -> None: diff --git a/tests/agent/test_onboarding.py b/tests/agent/test_onboarding.py index 1eaf0d01d2b..0ae03db3aa8 100644 --- a/tests/agent/test_onboarding.py +++ b/tests/agent/test_onboarding.py @@ -3,7 +3,6 @@ from __future__ import annotations import yaml -import pytest from agent.onboarding import ( BUSY_INPUT_FLAG, diff --git a/tests/agent/test_plugin_llm.py b/tests/agent/test_plugin_llm.py index b31f8097a7e..517bd2d224c 100644 --- a/tests/agent/test_plugin_llm.py +++ b/tests/agent/test_plugin_llm.py @@ -10,7 +10,6 @@ from __future__ import annotations import asyncio import base64 -import json from types import SimpleNamespace from typing import Any from unittest.mock import MagicMock diff --git a/tests/agent/test_prompt_builder.py b/tests/agent/test_prompt_builder.py index 1715bf00ce6..e0370c30905 100644 --- a/tests/agent/test_prompt_builder.py +++ b/tests/agent/test_prompt_builder.py @@ -18,7 +18,6 @@ from agent.prompt_builder import ( build_skills_system_prompt, build_nous_subscription_prompt, build_context_files_prompt, - build_environment_hints, CONTEXT_FILE_MAX_CHARS, DEFAULT_AGENT_IDENTITY, TOOL_USE_ENFORCEMENT_GUIDANCE, diff --git a/tests/agent/test_prompt_caching.py b/tests/agent/test_prompt_caching.py index f6f3e9f0a38..499ffc765a4 100644 --- a/tests/agent/test_prompt_caching.py +++ b/tests/agent/test_prompt_caching.py @@ -1,7 +1,5 @@ """Tests for agent/prompt_caching.py — Anthropic cache control injection.""" -import copy -import pytest from agent.prompt_caching import ( _apply_cache_marker, diff --git a/tests/agent/test_rate_limit_tracker.py b/tests/agent/test_rate_limit_tracker.py index caef785678b..63cdee2db91 100644 --- a/tests/agent/test_rate_limit_tracker.py +++ b/tests/agent/test_rate_limit_tracker.py @@ -189,14 +189,11 @@ class TestAgentIntegration: def test_capture_rate_limits_from_headers(self): """Simulate the header capture path without a real API call.""" - import sys - import os # Use a mock httpx-like response class MockResponse: headers = NOUS_HEADERS # Import AIAgent minimally - from unittest.mock import MagicMock, patch # Test the parsing directly state = parse_rate_limit_headers(MockResponse.headers, provider="nous") diff --git a/tests/agent/test_redact.py b/tests/agent/test_redact.py index 92fa13649a9..e4fa5e95043 100644 --- a/tests/agent/test_redact.py +++ b/tests/agent/test_redact.py @@ -1,7 +1,6 @@ """Tests for agent.redact -- secret masking in logs and output.""" import logging -import os import pytest diff --git a/tests/agent/test_shell_hooks.py b/tests/agent/test_shell_hooks.py index 743c9acb843..ce060f2f3c7 100644 --- a/tests/agent/test_shell_hooks.py +++ b/tests/agent/test_shell_hooks.py @@ -9,10 +9,7 @@ covered in ``test_shell_hooks_consent.py``. from __future__ import annotations import json -import os -import stat from pathlib import Path -from typing import Any, Dict import pytest diff --git a/tests/agent/test_shell_hooks_consent.py b/tests/agent/test_shell_hooks_consent.py index 2154dc84b2c..b64e79df4c7 100644 --- a/tests/agent/test_shell_hooks_consent.py +++ b/tests/agent/test_shell_hooks_consent.py @@ -7,7 +7,6 @@ hooks_auto_accept: config key). from __future__ import annotations -import json from pathlib import Path from unittest.mock import patch diff --git a/tests/agent/test_skill_bundles.py b/tests/agent/test_skill_bundles.py index fa9e42d43ec..96fe0a057f9 100644 --- a/tests/agent/test_skill_bundles.py +++ b/tests/agent/test_skill_bundles.py @@ -2,7 +2,6 @@ import os from pathlib import Path -from unittest.mock import patch import pytest diff --git a/tests/agent/test_subagent_progress.py b/tests/agent/test_subagent_progress.py index 953f26a69e8..761edf6ea73 100644 --- a/tests/agent/test_subagent_progress.py +++ b/tests/agent/test_subagent_progress.py @@ -10,10 +10,8 @@ Verifies that: import io import sys -import time -import threading import pytest -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock from agent.display import KawaiiSpinner from tools.delegate_tool import _build_child_progress_callback diff --git a/tests/agent/test_subdirectory_hints.py b/tests/agent/test_subdirectory_hints.py index cf445797cee..bc1f7f17f24 100644 --- a/tests/agent/test_subdirectory_hints.py +++ b/tests/agent/test_subdirectory_hints.py @@ -1,6 +1,5 @@ """Tests for progressive subdirectory hint discovery.""" -import os import pytest from pathlib import Path from unittest.mock import patch diff --git a/tests/agent/test_title_generator.py b/tests/agent/test_title_generator.py index c498a71ab50..56286f6ecc9 100644 --- a/tests/agent/test_title_generator.py +++ b/tests/agent/test_title_generator.py @@ -1,9 +1,7 @@ """Tests for agent.title_generator — auto-generated session titles.""" -import threading from unittest.mock import MagicMock, patch -import pytest from agent.title_generator import ( generate_title, diff --git a/tests/agent/transports/test_bedrock_transport.py b/tests/agent/transports/test_bedrock_transport.py index 7a5301d84fc..2f43daf988d 100644 --- a/tests/agent/transports/test_bedrock_transport.py +++ b/tests/agent/transports/test_bedrock_transport.py @@ -1,11 +1,10 @@ """Tests for the BedrockTransport.""" -import json import pytest from types import SimpleNamespace from agent.transports import get_transport -from agent.transports.types import NormalizedResponse, ToolCall +from agent.transports.types import NormalizedResponse @pytest.fixture diff --git a/tests/agent/transports/test_codex_app_server_session.py b/tests/agent/transports/test_codex_app_server_session.py index edddf6b433e..a0ee59d616d 100644 --- a/tests/agent/transports/test_codex_app_server_session.py +++ b/tests/agent/transports/test_codex_app_server_session.py @@ -7,7 +7,6 @@ deadline timeouts. These tests pin all of that without spawning real codex. from __future__ import annotations -import threading import time from unittest.mock import patch from typing import Any, Optional @@ -17,7 +16,6 @@ import pytest import agent.transports.codex_app_server_session as session_mod from agent.transports.codex_app_server_session import ( CodexAppServerSession, - TurnResult, _ServerRequestRouting, _approval_choice_to_codex_decision, _coerce_turn_input_text, diff --git a/tests/agent/transports/test_codex_event_projector.py b/tests/agent/transports/test_codex_event_projector.py index 04980f35c61..8da4d8e911f 100644 --- a/tests/agent/transports/test_codex_event_projector.py +++ b/tests/agent/transports/test_codex_event_projector.py @@ -11,7 +11,6 @@ import pytest from agent.transports.codex_event_projector import ( CodexEventProjector, - ProjectionResult, _deterministic_call_id, _format_tool_args, ) diff --git a/tests/agent/transports/test_codex_transport.py b/tests/agent/transports/test_codex_transport.py index 1309c979218..5d8aa6ba12b 100644 --- a/tests/agent/transports/test_codex_transport.py +++ b/tests/agent/transports/test_codex_transport.py @@ -5,7 +5,7 @@ import pytest from types import SimpleNamespace from agent.transports import get_transport -from agent.transports.types import NormalizedResponse, ToolCall +from agent.transports.types import NormalizedResponse @pytest.fixture diff --git a/tests/agent/transports/test_hermes_tools_mcp_server.py b/tests/agent/transports/test_hermes_tools_mcp_server.py index 3c11cb3f81d..c61e6c684ea 100644 --- a/tests/agent/transports/test_hermes_tools_mcp_server.py +++ b/tests/agent/transports/test_hermes_tools_mcp_server.py @@ -8,9 +8,7 @@ build helper assembles a server when the SDK is present. from __future__ import annotations -from unittest.mock import patch -import pytest class TestModuleSurface: diff --git a/tests/agent/transports/test_transport.py b/tests/agent/transports/test_transport.py index 67fb486fc9a..18b210b7c31 100644 --- a/tests/agent/transports/test_transport.py +++ b/tests/agent/transports/test_transport.py @@ -2,10 +2,9 @@ import pytest from types import SimpleNamespace -from unittest.mock import MagicMock from agent.transports.base import ProviderTransport -from agent.transports.types import NormalizedResponse, ToolCall, Usage +from agent.transports.types import NormalizedResponse from agent.transports import get_transport, register_transport, _REGISTRY diff --git a/tests/agent/transports/test_types.py b/tests/agent/transports/test_types.py index 2d576a8f83c..c52e77e330f 100644 --- a/tests/agent/transports/test_types.py +++ b/tests/agent/transports/test_types.py @@ -1,7 +1,6 @@ """Tests for agent/transports/types.py — dataclass construction + helpers.""" import json -import pytest from agent.transports.types import ( NormalizedResponse, diff --git a/tests/cli/test_branch_command.py b/tests/cli/test_branch_command.py index cf48384403f..8f8a70749b8 100644 --- a/tests/cli/test_branch_command.py +++ b/tests/cli/test_branch_command.py @@ -10,10 +10,8 @@ Verifies that: """ import os -import uuid from datetime import datetime -from pathlib import Path -from unittest.mock import MagicMock, patch, PropertyMock +from unittest.mock import MagicMock import pytest diff --git a/tests/cli/test_cli_background_tui_refresh.py b/tests/cli/test_cli_background_tui_refresh.py index 924df1026ad..7f86568cc32 100644 --- a/tests/cli/test_cli_background_tui_refresh.py +++ b/tests/cli/test_cli_background_tui_refresh.py @@ -4,11 +4,8 @@ Ensures the TUI is properly refreshed before printing background task output to prevent spinner/status bar overlap (#2718). """ -import threading -from types import SimpleNamespace from unittest.mock import MagicMock, patch -import pytest from cli import HermesCLI diff --git a/tests/cli/test_cli_file_drop.py b/tests/cli/test_cli_file_drop.py index a7a8c42e2da..4109ade9f3d 100644 --- a/tests/cli/test_cli_file_drop.py +++ b/tests/cli/test_cli_file_drop.py @@ -1,9 +1,6 @@ """Tests for _detect_file_drop — file path detection that prevents dragged/pasted absolute paths from being mistaken for slash commands.""" -import os -import tempfile -from pathlib import Path import pytest diff --git a/tests/cli/test_cli_goal_interrupt.py b/tests/cli/test_cli_goal_interrupt.py index 851b87e856b..0ef04149038 100644 --- a/tests/cli/test_cli_goal_interrupt.py +++ b/tests/cli/test_cli_goal_interrupt.py @@ -12,7 +12,6 @@ minimal ``HermesCLI`` stub (pattern used elsewhere in tests/cli). from __future__ import annotations import queue -import sys import uuid from pathlib import Path from unittest.mock import MagicMock, patch diff --git a/tests/cli/test_cli_interrupt_subagent.py b/tests/cli/test_cli_interrupt_subagent.py index 6821a6725d4..5b732425c8a 100644 --- a/tests/cli/test_cli_interrupt_subagent.py +++ b/tests/cli/test_cli_interrupt_subagent.py @@ -10,15 +10,12 @@ This tests the COMPLETE path including _run_single_child, _active_children registration, interrupt propagation, and child detection. """ -import json -import os -import queue import threading import time import unittest -from unittest.mock import MagicMock, patch, PropertyMock +from unittest.mock import MagicMock, patch -from tools.interrupt import set_interrupt, is_interrupted +from tools.interrupt import set_interrupt class TestCLISubagentInterrupt(unittest.TestCase): diff --git a/tests/cli/test_cli_light_mode.py b/tests/cli/test_cli_light_mode.py index bc5ca5128e0..c1df160e6b1 100644 --- a/tests/cli/test_cli_light_mode.py +++ b/tests/cli/test_cli_light_mode.py @@ -8,7 +8,6 @@ before the terminal query, which is the path most users hit. from __future__ import annotations -import importlib import pytest diff --git a/tests/cli/test_cli_status_bar.py b/tests/cli/test_cli_status_bar.py index 47bd68aa25d..f62287f622b 100644 --- a/tests/cli/test_cli_status_bar.py +++ b/tests/cli/test_cli_status_bar.py @@ -568,7 +568,6 @@ class TestStatusBarWidthSource: """Ensure status bar fragments don't overflow the terminal width.""" def _make_wide_cli(self): - from datetime import datetime, timedelta cli_obj = _attach_agent( _make_cli(), prompt_tokens=100_000, diff --git a/tests/cli/test_cli_tools_command.py b/tests/cli/test_cli_tools_command.py index 2f0b096d2e6..15cfce105b6 100644 --- a/tests/cli/test_cli_tools_command.py +++ b/tests/cli/test_cli_tools_command.py @@ -1,6 +1,6 @@ """Tests for /tools slash command handler in the interactive CLI.""" -from unittest.mock import MagicMock, patch, call +from unittest.mock import MagicMock, patch from cli import HermesCLI diff --git a/tests/cli/test_cwd_env_respect.py b/tests/cli/test_cwd_env_respect.py index 04e62cc12f8..49f0e603964 100644 --- a/tests/cli/test_cwd_env_respect.py +++ b/tests/cli/test_cwd_env_respect.py @@ -6,8 +6,6 @@ Rules: - Non-local with explicit path: keep as-is. """ -import os -import pytest _CWD_PLACEHOLDERS = (".", "auto", "cwd") diff --git a/tests/cli/test_personality_none.py b/tests/cli/test_personality_none.py index ad5e87e880a..3fa1ab2a693 100644 --- a/tests/cli/test_personality_none.py +++ b/tests/cli/test_personality_none.py @@ -1,6 +1,6 @@ """Tests for /personality none — clearing personality overlay.""" import pytest -from unittest.mock import MagicMock, patch, mock_open +from unittest.mock import MagicMock, patch import yaml diff --git a/tests/cli/test_quick_commands.py b/tests/cli/test_quick_commands.py index 57a39e8c53d..5f4ce2d32ac 100644 --- a/tests/cli/test_quick_commands.py +++ b/tests/cli/test_quick_commands.py @@ -1,7 +1,7 @@ """Tests for user-defined quick commands that bypass the agent loop.""" import os import subprocess -from unittest.mock import MagicMock, patch, AsyncMock +from unittest.mock import MagicMock, patch from rich.text import Text import pytest diff --git a/tests/cli/test_resume_display.py b/tests/cli/test_resume_display.py index be9282f8595..5ccac59ba6e 100644 --- a/tests/cli/test_resume_display.py +++ b/tests/cli/test_resume_display.py @@ -10,7 +10,6 @@ import sys from io import StringIO from unittest.mock import MagicMock, patch -import pytest import cli as cli_mod sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) @@ -719,7 +718,6 @@ class TestResumeDisplayConfig: def test_cli_defaults_have_resume_display(self): """cli.py load_cli_config defaults include resume_display.""" - import cli as _cli_mod from cli import load_cli_config with ( diff --git a/tests/cli/test_resume_quiet_stderr.py b/tests/cli/test_resume_quiet_stderr.py index c3421a105ec..df82ce4dda9 100644 --- a/tests/cli/test_resume_quiet_stderr.py +++ b/tests/cli/test_resume_quiet_stderr.py @@ -13,7 +13,6 @@ Interactive mode (tool_progress_mode == "full") still uses ChatConsole. from datetime import datetime from unittest.mock import MagicMock, patch -import pytest from cli import HermesCLI diff --git a/tests/cli/test_save_conversation_location.py b/tests/cli/test_save_conversation_location.py index 972c8fcb159..5e460fe81bc 100644 --- a/tests/cli/test_save_conversation_location.py +++ b/tests/cli/test_save_conversation_location.py @@ -11,7 +11,6 @@ the absolute path plus the resume hint for the live session. from __future__ import annotations import json -import os import sys from datetime import datetime from pathlib import Path diff --git a/tests/cli/test_session_boundary_hooks.py b/tests/cli/test_session_boundary_hooks.py index 19de4cd97a3..3fcab991e95 100644 --- a/tests/cli/test_session_boundary_hooks.py +++ b/tests/cli/test_session_boundary_hooks.py @@ -1,9 +1,5 @@ -import pytest from unittest.mock import MagicMock, patch from hermes_cli.plugins import VALID_HOOKS, PluginManager -import os -import shutil -import tempfile from cli import HermesCLI diff --git a/tests/cli/test_slash_command_interrupt.py b/tests/cli/test_slash_command_interrupt.py index 37e38c8c5f2..70f9799693c 100644 --- a/tests/cli/test_slash_command_interrupt.py +++ b/tests/cli/test_slash_command_interrupt.py @@ -11,7 +11,7 @@ prompt_toolkit input loop. We exercise the same try/except by calling through a thin wrapper that mirrors the real dispatch shape. """ -from unittest.mock import MagicMock, patch +from unittest.mock import patch from cli import HermesCLI diff --git a/tests/cli/test_slash_confirm_windows.py b/tests/cli/test_slash_confirm_windows.py index 980bae32d26..c067bd791ca 100644 --- a/tests/cli/test_slash_confirm_windows.py +++ b/tests/cli/test_slash_confirm_windows.py @@ -20,7 +20,6 @@ import threading import time from unittest.mock import MagicMock, patch -import pytest def _make_cli(): diff --git a/tests/cli/test_stream_delta_think_tag.py b/tests/cli/test_stream_delta_think_tag.py index e7c406b37ba..93c738b7304 100644 --- a/tests/cli/test_stream_delta_think_tag.py +++ b/tests/cli/test_stream_delta_think_tag.py @@ -3,7 +3,6 @@ import sys import os sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..")) -import pytest def _make_cli_stub(): diff --git a/tests/cli/test_surrogate_sanitization.py b/tests/cli/test_surrogate_sanitization.py index 9d677352c99..2a04a5c246f 100644 --- a/tests/cli/test_surrogate_sanitization.py +++ b/tests/cli/test_surrogate_sanitization.py @@ -13,7 +13,6 @@ from run_agent import ( _sanitize_surrogates, _sanitize_messages_surrogates, _sanitize_structure_surrogates, - _SURROGATE_RE, ) diff --git a/tests/cli/test_worktree.py b/tests/cli/test_worktree.py index b139acf7d2f..221903e0e96 100644 --- a/tests/cli/test_worktree.py +++ b/tests/cli/test_worktree.py @@ -9,7 +9,6 @@ import shutil import subprocess import pytest from pathlib import Path -from unittest.mock import patch, MagicMock @pytest.fixture @@ -397,7 +396,6 @@ class TestWorktreeInclude: assert info is not None # Manually copy .worktreeinclude entries (mirrors cli.py logic) - import shutil include_file = git_repo / ".worktreeinclude" wt_path = Path(info["path"]) for line in include_file.read_text().splitlines(): diff --git a/tests/conftest.py b/tests/conftest.py index fcb19c71fb4..17bc68d8031 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -21,10 +21,8 @@ test runner at ``scripts/run_tests.sh``. import asyncio import os -import re import sys from pathlib import Path -from unittest.mock import patch import pytest diff --git a/tests/cron/test_cron_context_from.py b/tests/cron/test_cron_context_from.py index f0277d25e1c..5dabaa37782 100644 --- a/tests/cron/test_cron_context_from.py +++ b/tests/cron/test_cron_context_from.py @@ -45,7 +45,7 @@ class TestJobContextFromField: assert loaded["context_from"] == [job_a["id"]] def test_create_job_with_context_from_list(self, cron_env): - from cron.jobs import create_job, get_job + from cron.jobs import create_job job_a = create_job(prompt="Find news", schedule="every 1h") job_b = create_job(prompt="Find weather", schedule="every 1h") diff --git a/tests/cron/test_cron_inactivity_timeout.py b/tests/cron/test_cron_inactivity_timeout.py index 67e932089f7..5394a50f368 100644 --- a/tests/cron/test_cron_inactivity_timeout.py +++ b/tests/cron/test_cron_inactivity_timeout.py @@ -12,11 +12,8 @@ import concurrent.futures import os import sys import time -import threading from pathlib import Path -from unittest.mock import MagicMock, patch -import pytest # Ensure project root is importable sys.path.insert(0, str(Path(__file__).parent.parent.parent)) diff --git a/tests/cron/test_cron_no_agent.py b/tests/cron/test_cron_no_agent.py index 583cd34099e..af94713868b 100644 --- a/tests/cron/test_cron_no_agent.py +++ b/tests/cron/test_cron_no_agent.py @@ -12,7 +12,6 @@ Covers: from __future__ import annotations import json -from pathlib import Path from unittest.mock import patch import pytest diff --git a/tests/cron/test_cron_profile.py b/tests/cron/test_cron_profile.py index 887849e635f..7ed28ba381e 100644 --- a/tests/cron/test_cron_profile.py +++ b/tests/cron/test_cron_profile.py @@ -8,7 +8,6 @@ from __future__ import annotations import json import os -from pathlib import Path import pytest diff --git a/tests/cron/test_cron_script.py b/tests/cron/test_cron_script.py index 2905339bece..7a6a06d5348 100644 --- a/tests/cron/test_cron_script.py +++ b/tests/cron/test_cron_script.py @@ -9,11 +9,9 @@ Tests cover: import json import os -import stat import sys import textwrap from pathlib import Path -from unittest.mock import patch import pytest diff --git a/tests/cron/test_cron_workdir.py b/tests/cron/test_cron_workdir.py index 5f317c4f4c2..678038cb59b 100644 --- a/tests/cron/test_cron_workdir.py +++ b/tests/cron/test_cron_workdir.py @@ -13,7 +13,6 @@ Covers: from __future__ import annotations import json -from pathlib import Path import pytest diff --git a/tests/cron/test_file_permissions.py b/tests/cron/test_file_permissions.py index cc816f6fa85..3f146829d80 100644 --- a/tests/cron/test_file_permissions.py +++ b/tests/cron/test_file_permissions.py @@ -1,6 +1,5 @@ """Tests for file permissions hardening on sensitive files.""" -import json import os import stat import tempfile diff --git a/tests/cron/test_jobs.py b/tests/cron/test_jobs.py index d1e5df48be8..d044f051ff1 100644 --- a/tests/cron/test_jobs.py +++ b/tests/cron/test_jobs.py @@ -1,11 +1,8 @@ """Tests for cron/jobs.py — schedule parsing, job CRUD, and due-job detection.""" -import json import threading import pytest from datetime import datetime, timedelta, timezone -from pathlib import Path -from unittest.mock import patch from cron.jobs import ( parse_duration, diff --git a/tests/cron/test_scheduler.py b/tests/cron/test_scheduler.py index 073d0d8510e..38da3fe4087 100644 --- a/tests/cron/test_scheduler.py +++ b/tests/cron/test_scheduler.py @@ -1275,7 +1275,6 @@ class TestRunJobSessionPersistence: (issue #8585) """ from cron.scheduler import tick - from cron.jobs import load_jobs, save_jobs job = { "id": "empty-job", @@ -2300,7 +2299,6 @@ class TestParallelTick: def test_parallel_jobs_run_concurrently(self): """Two jobs launched in the same tick should overlap in time.""" import threading - import time barrier = threading.Barrier(2, timeout=5) call_order = [] diff --git a/tests/cron/test_scheduler_mcp_init.py b/tests/cron/test_scheduler_mcp_init.py index b751f0f00b2..a951fe4a7cf 100644 --- a/tests/cron/test_scheduler_mcp_init.py +++ b/tests/cron/test_scheduler_mcp_init.py @@ -15,9 +15,8 @@ short-circuit on already-connected servers. from __future__ import annotations -from unittest.mock import patch, MagicMock +from unittest.mock import patch -import pytest diff --git a/tests/e2e/matrix_xsign_bootstrap/test_bootstrap.py b/tests/e2e/matrix_xsign_bootstrap/test_bootstrap.py index 09147ba55e7..c24c7292073 100644 --- a/tests/e2e/matrix_xsign_bootstrap/test_bootstrap.py +++ b/tests/e2e/matrix_xsign_bootstrap/test_bootstrap.py @@ -27,7 +27,6 @@ isn't reachable. """ from __future__ import annotations -import asyncio import json import logging import os @@ -37,7 +36,6 @@ import shutil import subprocess import sys import tempfile -import time import unittest import urllib.error import urllib.request diff --git a/tests/gateway/conftest.py b/tests/gateway/conftest.py index 258ee15656c..2d56c7c11f4 100644 --- a/tests/gateway/conftest.py +++ b/tests/gateway/conftest.py @@ -419,7 +419,6 @@ def pytest_configure(config): lock = FileLock(str(lock_file), timeout=120) except ImportError: # Fallback: no locking (still correct, just slower under contention). - import contextlib class _NoLock: def __enter__(self): diff --git a/tests/gateway/restart_test_helpers.py b/tests/gateway/restart_test_helpers.py index 213c46cbad8..a91816c4e20 100644 --- a/tests/gateway/restart_test_helpers.py +++ b/tests/gateway/restart_test_helpers.py @@ -3,7 +3,7 @@ from collections import OrderedDict from unittest.mock import AsyncMock, MagicMock from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import BasePlatformAdapter, MessageEvent, SendResult +from gateway.platforms.base import BasePlatformAdapter, SendResult from gateway.restart import DEFAULT_GATEWAY_RESTART_DRAIN_TIMEOUT from gateway.run import GatewayRunner from gateway.session import SessionSource diff --git a/tests/gateway/test_7100_transient_failure_transcript.py b/tests/gateway/test_7100_transient_failure_transcript.py index 3340dc28d51..cb416e6b9ad 100644 --- a/tests/gateway/test_7100_transient_failure_transcript.py +++ b/tests/gateway/test_7100_transient_failure_transcript.py @@ -15,7 +15,6 @@ The gateway classifier must distinguish: * everything else that fails → transient → persist the user message """ -import pytest def _classify(agent_result: dict, history_len: int) -> tuple[bool, bool]: diff --git a/tests/gateway/test_agent_cache.py b/tests/gateway/test_agent_cache.py index 6ef601e0dc5..0c6e2df3bd9 100644 --- a/tests/gateway/test_agent_cache.py +++ b/tests/gateway/test_agent_cache.py @@ -9,12 +9,9 @@ Verifies that the agent cache correctly: - Preserves frozen system prompt across turns """ -import hashlib -import json import threading from unittest.mock import MagicMock, patch -import pytest def _make_runner(): diff --git a/tests/gateway/test_allowed_channels_widening.py b/tests/gateway/test_allowed_channels_widening.py index 6d4c8d1ead0..0d214713a1c 100644 --- a/tests/gateway/test_allowed_channels_widening.py +++ b/tests/gateway/test_allowed_channels_widening.py @@ -243,7 +243,6 @@ class TestMattermostAllowedChannels: @staticmethod def _would_process(channel_id, channel_type="O", allowed_cfg=None, allowed_env=""): """Replicate the whitelist gate from gateway/platforms/mattermost.py.""" - import os as _os if channel_type == "D": return True # config-first, env-var fallback (matching the adapter) diff --git a/tests/gateway/test_api_server.py b/tests/gateway/test_api_server.py index 3b0a9b24b6f..c042fd556c6 100644 --- a/tests/gateway/test_api_server.py +++ b/tests/gateway/test_api_server.py @@ -22,14 +22,13 @@ from unittest.mock import AsyncMock, MagicMock, patch import pytest from aiohttp import web -from aiohttp.test_utils import AioHTTPTestCase, TestClient, TestServer +from aiohttp.test_utils import TestClient, TestServer from gateway.config import GatewayConfig, Platform, PlatformConfig from gateway.platforms.api_server import ( APIServerAdapter, ResponseStore, _IdempotencyCache, - _CORS_HEADERS, _derive_chat_session_id, check_api_server_requirements, cors_middleware, diff --git a/tests/gateway/test_api_server_bind_guard.py b/tests/gateway/test_api_server_bind_guard.py index fa43f8c4630..edab34eb382 100644 --- a/tests/gateway/test_api_server_bind_guard.py +++ b/tests/gateway/test_api_server_bind_guard.py @@ -5,7 +5,7 @@ that connect() refuses to start without API_SERVER_KEY. """ import socket -from unittest.mock import AsyncMock, patch +from unittest.mock import patch import pytest diff --git a/tests/gateway/test_api_server_jobs.py b/tests/gateway/test_api_server_jobs.py index 087bfc5b404..7e1f4cc4103 100644 --- a/tests/gateway/test_api_server_jobs.py +++ b/tests/gateway/test_api_server_jobs.py @@ -10,7 +10,6 @@ Covers: - Cron module unavailability (501 when _CRON_AVAILABLE is False) """ -import json import logging from unittest.mock import MagicMock, patch diff --git a/tests/gateway/test_api_server_runs.py b/tests/gateway/test_api_server_runs.py index dd25ea97160..d6e1e588506 100644 --- a/tests/gateway/test_api_server_runs.py +++ b/tests/gateway/test_api_server_runs.py @@ -9,10 +9,8 @@ Covers: """ import asyncio -import json import threading -import time as _time -from unittest.mock import AsyncMock, MagicMock, patch +from unittest.mock import MagicMock, patch import pytest from aiohttp import web diff --git a/tests/gateway/test_api_server_toolset.py b/tests/gateway/test_api_server_toolset.py index 943d867e613..add2ce27345 100644 --- a/tests/gateway/test_api_server_toolset.py +++ b/tests/gateway/test_api_server_toolset.py @@ -1,9 +1,6 @@ """Tests for hermes-api-server toolset and API server tool availability.""" -import os -import json from unittest.mock import patch, MagicMock -import pytest from toolsets import resolve_toolset, get_toolset, validate_toolset diff --git a/tests/gateway/test_approve_deny_commands.py b/tests/gateway/test_approve_deny_commands.py index 02834fce8e4..1c996b2baee 100644 --- a/tests/gateway/test_approve_deny_commands.py +++ b/tests/gateway/test_approve_deny_commands.py @@ -8,7 +8,6 @@ Supports multiple concurrent approvals (parallel subagents, execute_code) via a per-session queue. """ -import asyncio import os import threading import time @@ -19,7 +18,7 @@ import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig from gateway.platforms.base import MessageEvent -from gateway.session import SessionEntry, SessionSource, build_session_key +from gateway.session import SessionSource def _make_source() -> SessionSource: @@ -635,7 +634,7 @@ class TestFallbackNoCallback: to ``pending_approval`` to make the state distinguishable from a failed tool call. """ - from tools.approval import check_all_command_guards, _pending + from tools.approval import check_all_command_guards os.environ["HERMES_EXEC_ASK"] = "1" os.environ["HERMES_SESSION_KEY"] = "no-callback-test" diff --git a/tests/gateway/test_auth_fallback.py b/tests/gateway/test_auth_fallback.py index 5976962e651..58701160e6c 100644 --- a/tests/gateway/test_auth_fallback.py +++ b/tests/gateway/test_auth_fallback.py @@ -1,7 +1,6 @@ """Test that AuthError triggers fallback provider resolution (#7230).""" -import os -from unittest.mock import patch, MagicMock +from unittest.mock import patch import pytest diff --git a/tests/gateway/test_auto_continue.py b/tests/gateway/test_auto_continue.py index 1f44fa6ab1d..eb20abf55df 100644 --- a/tests/gateway/test_auto_continue.py +++ b/tests/gateway/test_auto_continue.py @@ -6,7 +6,6 @@ this and prepends a system note to the next user message so the model finishes the interrupted work before addressing the new input. """ -import pytest def _simulate_auto_continue(agent_history: list, user_message: str) -> str: diff --git a/tests/gateway/test_background_command.py b/tests/gateway/test_background_command.py index 9e0d71921cd..b729ab6563f 100644 --- a/tests/gateway/test_background_command.py +++ b/tests/gateway/test_background_command.py @@ -5,7 +5,6 @@ background session) across gateway messenger platforms. """ import asyncio -import os from unittest.mock import AsyncMock, MagicMock, patch import pytest diff --git a/tests/gateway/test_background_process_notifications.py b/tests/gateway/test_background_process_notifications.py index 412b780bb6f..fe3a6588b1b 100644 --- a/tests/gateway/test_background_process_notifications.py +++ b/tests/gateway/test_background_process_notifications.py @@ -9,7 +9,7 @@ Contributed by @PeterFile (PR #593), reimplemented on current main. import asyncio from types import SimpleNamespace -from unittest.mock import AsyncMock, patch +from unittest.mock import AsyncMock import pytest diff --git a/tests/gateway/test_bluebubbles.py b/tests/gateway/test_bluebubbles.py index dea806fe66b..e42d050c817 100644 --- a/tests/gateway/test_bluebubbles.py +++ b/tests/gateway/test_bluebubbles.py @@ -302,7 +302,6 @@ class TestBlueBubblesAttachmentDownload: """Image MIME routes to cache_image_from_bytes.""" adapter = _make_adapter(monkeypatch) import asyncio - import httpx # Mock the HTTP client response class MockResponse: diff --git a/tests/gateway/test_busy_session_ack.py b/tests/gateway/test_busy_session_ack.py index 798dba8462f..7fb3d3210c0 100644 --- a/tests/gateway/test_busy_session_ack.py +++ b/tests/gateway/test_busy_session_ack.py @@ -3,7 +3,6 @@ Verifies that users get an immediate status response instead of total silence when the agent is working on a task. See PR fix for the @Lonely__MH report. """ -import asyncio import time from unittest.mock import AsyncMock, MagicMock, patch @@ -26,7 +25,6 @@ sys.modules.setdefault("telegram.constants", _tg.constants) sys.modules.setdefault("telegram.ext", types.ModuleType("telegram.ext")) from gateway.platforms.base import ( - BasePlatformAdapter, MessageEvent, MessageType, SessionSource, diff --git a/tests/gateway/test_busy_session_auth_bypass.py b/tests/gateway/test_busy_session_auth_bypass.py index 9d7146c848e..b1c25a12d87 100644 --- a/tests/gateway/test_busy_session_auth_bypass.py +++ b/tests/gateway/test_busy_session_auth_bypass.py @@ -5,9 +5,8 @@ messages from non-allowlisted users must be silently dropped — matching the co behavior in _handle_message. Previously, the busy path skipped the auth check entirely, allowing unauthorized users to inject text into another user's running session. """ -import asyncio import time -from unittest.mock import AsyncMock, MagicMock, patch +from unittest.mock import AsyncMock, MagicMock import pytest @@ -27,12 +26,10 @@ sys.modules.setdefault("telegram.constants", _tg.constants) sys.modules.setdefault("telegram.ext", types.ModuleType("telegram.ext")) from gateway.platforms.base import ( - BasePlatformAdapter, MessageEvent, MessageType, SessionSource, build_session_key, - merge_pending_message_event, ) diff --git a/tests/gateway/test_channel_directory.py b/tests/gateway/test_channel_directory.py index cdaf2c540c3..18e8ae2fb09 100644 --- a/tests/gateway/test_channel_directory.py +++ b/tests/gateway/test_channel_directory.py @@ -3,7 +3,6 @@ import asyncio import json import os -from pathlib import Path from types import SimpleNamespace from unittest.mock import AsyncMock, MagicMock, patch @@ -15,7 +14,6 @@ from gateway.channel_directory import ( load_directory, _build_from_sessions, _build_slack, - DIRECTORY_PATH, ) diff --git a/tests/gateway/test_clean_shutdown_marker.py b/tests/gateway/test_clean_shutdown_marker.py index c6d3cab5c13..45e56171b8b 100644 --- a/tests/gateway/test_clean_shutdown_marker.py +++ b/tests/gateway/test_clean_shutdown_marker.py @@ -7,15 +7,12 @@ suspend_recently_active() is skipped so users don't lose their sessions. After a crash (no marker), suspension still fires as a safety net for stuck sessions. """ -import os from datetime import datetime, timedelta -from pathlib import Path from unittest.mock import AsyncMock, MagicMock, patch -import pytest -from gateway.config import GatewayConfig, Platform, PlatformConfig, SessionResetPolicy -from gateway.session import SessionEntry, SessionSource, SessionStore +from gateway.config import GatewayConfig, Platform +from gateway.session import SessionSource, SessionStore # --------------------------------------------------------------------------- diff --git a/tests/gateway/test_command_bypass_active_session.py b/tests/gateway/test_command_bypass_active_session.py index 2c0a593dc55..e5e8a4fa469 100644 --- a/tests/gateway/test_command_bypass_active_session.py +++ b/tests/gateway/test_command_bypass_active_session.py @@ -13,7 +13,6 @@ the safety net in _run_agent discards leaked command text. """ import asyncio -from unittest.mock import AsyncMock, MagicMock import pytest diff --git a/tests/gateway/test_config_cwd_bridge.py b/tests/gateway/test_config_cwd_bridge.py index 6aaf9721cf2..05ffee9b8d2 100644 --- a/tests/gateway/test_config_cwd_bridge.py +++ b/tests/gateway/test_config_cwd_bridge.py @@ -11,7 +11,6 @@ asserting the expected env var outcomes. import os import json -import pytest def _simulate_config_bridge(cfg: dict, initial_env: dict | None = None): diff --git a/tests/gateway/test_dingtalk.py b/tests/gateway/test_dingtalk.py index 2da55a00979..d73b687d7ac 100644 --- a/tests/gateway/test_dingtalk.py +++ b/tests/gateway/test_dingtalk.py @@ -1,9 +1,8 @@ """Tests for DingTalk platform adapter.""" import asyncio -import json from datetime import datetime, timezone from types import SimpleNamespace -from unittest.mock import AsyncMock, MagicMock, patch, PropertyMock +from unittest.mock import AsyncMock, MagicMock, patch import pytest diff --git a/tests/gateway/test_discord_bot_auth_bypass.py b/tests/gateway/test_discord_bot_auth_bypass.py index 7d86e034eb3..8e10dfbcb94 100644 --- a/tests/gateway/test_discord_bot_auth_bypass.py +++ b/tests/gateway/test_discord_bot_auth_bypass.py @@ -13,9 +13,7 @@ These tests assert both gates now pass a bot message through when DISCORD_ALLOW_BOTS permits it AND no user allowlist entry exists. """ -import os from types import SimpleNamespace -from unittest.mock import patch import pytest diff --git a/tests/gateway/test_discord_bot_filter.py b/tests/gateway/test_discord_bot_filter.py index 09a78ae6308..90dc9f8de00 100644 --- a/tests/gateway/test_discord_bot_filter.py +++ b/tests/gateway/test_discord_bot_filter.py @@ -1,9 +1,8 @@ """Tests for Discord bot message filtering (DISCORD_ALLOW_BOTS).""" -import asyncio import os import unittest -from unittest.mock import AsyncMock, MagicMock, patch +from unittest.mock import MagicMock def _make_author(*, bot: bool = False, is_self: bool = False): diff --git a/tests/gateway/test_discord_channel_skills.py b/tests/gateway/test_discord_channel_skills.py index 33c469df60d..a1b958d06b0 100644 --- a/tests/gateway/test_discord_channel_skills.py +++ b/tests/gateway/test_discord_channel_skills.py @@ -1,6 +1,5 @@ """Tests for Discord channel_skill_bindings auto-skill resolution.""" from unittest.mock import MagicMock -import pytest def _make_adapter(): diff --git a/tests/gateway/test_discord_clarify_buttons.py b/tests/gateway/test_discord_clarify_buttons.py index 04f20195f46..d2157f2eb9b 100644 --- a/tests/gateway/test_discord_clarify_buttons.py +++ b/tests/gateway/test_discord_clarify_buttons.py @@ -11,7 +11,6 @@ dispatcher like Telegram — the auth + resolution path is the same: · already-resolved or unauthorized → ephemeral "this prompt..." reply """ -import asyncio import sys from pathlib import Path from types import SimpleNamespace @@ -170,7 +169,6 @@ class TestClarifyChoiceResolve: async def test_choice_falls_back_to_label_text_when_entry_missing(self): """If the gateway entry vanished (race / stale view), the button's own choice text is used as the response.""" - from tools import clarify_gateway as cm # Note: no cm.register() — entry intentionally absent view = ClarifyChoiceView( diff --git a/tests/gateway/test_discord_lazy_install_views.py b/tests/gateway/test_discord_lazy_install_views.py index 2ed926e0f8f..7ca100ef81b 100644 --- a/tests/gateway/test_discord_lazy_install_views.py +++ b/tests/gateway/test_discord_lazy_install_views.py @@ -15,10 +15,8 @@ Fixes: lazy-install path NameError for ExecApprovalView, SlashConfirmView, UpdatePromptView, ModelPickerView, ClarifyChoiceView. """ import importlib -import sys from unittest.mock import patch -import pytest _VIEW_NAMES = [ "ExecApprovalView", diff --git a/tests/gateway/test_discord_roles_dm_scope.py b/tests/gateway/test_discord_roles_dm_scope.py index ee2939aae3b..19d65a5998c 100644 --- a/tests/gateway/test_discord_roles_dm_scope.py +++ b/tests/gateway/test_discord_roles_dm_scope.py @@ -18,7 +18,6 @@ opts into a single trusted guild. from types import SimpleNamespace from unittest.mock import MagicMock -import pytest from plugins.platforms.discord.adapter import DiscordAdapter diff --git a/tests/gateway/test_discord_thread_persistence.py b/tests/gateway/test_discord_thread_persistence.py index 75237f6403f..41ffcb2b5bb 100644 --- a/tests/gateway/test_discord_thread_persistence.py +++ b/tests/gateway/test_discord_thread_persistence.py @@ -8,7 +8,6 @@ import json import os from unittest.mock import patch -import pytest class TestDiscordThreadPersistence: diff --git a/tests/gateway/test_display_config.py b/tests/gateway/test_display_config.py index 5f23edbd4f5..75230e5b9cd 100644 --- a/tests/gateway/test_display_config.py +++ b/tests/gateway/test_display_config.py @@ -1,5 +1,4 @@ """Tests for gateway.display_config — per-platform display/verbosity resolver.""" -import pytest # --------------------------------------------------------------------------- diff --git a/tests/gateway/test_dm_topics.py b/tests/gateway/test_dm_topics.py index 332375229c5..3f6b0942803 100644 --- a/tests/gateway/test_dm_topics.py +++ b/tests/gateway/test_dm_topics.py @@ -9,12 +9,11 @@ Covers: - _build_message_event: DM topic resolution in message events """ -import asyncio import os import sys from pathlib import Path from types import SimpleNamespace -from unittest.mock import AsyncMock, MagicMock, patch, mock_open +from unittest.mock import AsyncMock, MagicMock, patch import pytest diff --git a/tests/gateway/test_duplicate_reply_suppression.py b/tests/gateway/test_duplicate_reply_suppression.py index 7e54515d6a6..c7c047fdb65 100644 --- a/tests/gateway/test_duplicate_reply_suppression.py +++ b/tests/gateway/test_duplicate_reply_suppression.py @@ -14,7 +14,6 @@ Covers four fix paths: import asyncio from types import SimpleNamespace -from unittest.mock import AsyncMock, MagicMock, patch import pytest @@ -22,8 +21,6 @@ from gateway.config import Platform, PlatformConfig from gateway.platforms.base import ( BasePlatformAdapter, MessageEvent, - MessageType, - ProcessingOutcome, SendResult, ) from gateway.session import SessionSource, build_session_key diff --git a/tests/gateway/test_email.py b/tests/gateway/test_email.py index 78034fe8075..2354f9ec201 100644 --- a/tests/gateway/test_email.py +++ b/tests/gateway/test_email.py @@ -18,8 +18,6 @@ from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from email.mime.base import MIMEBase from email import encoders -from pathlib import Path -from types import SimpleNamespace from unittest.mock import patch, MagicMock, AsyncMock from gateway.platforms.base import SendResult @@ -660,7 +658,6 @@ class TestSendMethods(unittest.TestCase): def test_send_image_includes_url(self): """send_image should include image URL in email body.""" import asyncio - from unittest.mock import AsyncMock adapter = self._make_adapter() adapter.send = AsyncMock(return_value=SendResult(success=True)) diff --git a/tests/gateway/test_extract_local_files.py b/tests/gateway/test_extract_local_files.py index 568b311cb9b..1a1111f948c 100644 --- a/tests/gateway/test_extract_local_files.py +++ b/tests/gateway/test_extract_local_files.py @@ -8,7 +8,6 @@ deduplication, text cleanup, and extension routing. Based on PR #1636 by sudoingX (salvaged + hardened). """ -import os from unittest.mock import patch import pytest diff --git a/tests/gateway/test_fallback_eviction.py b/tests/gateway/test_fallback_eviction.py index ae3ed07aa54..677172e8e0b 100644 --- a/tests/gateway/test_fallback_eviction.py +++ b/tests/gateway/test_fallback_eviction.py @@ -7,9 +7,7 @@ Eviction should only happen on successful runs where fallback activated. import sys from pathlib import Path -from unittest.mock import MagicMock, patch -import pytest sys.path.insert(0, str(Path(__file__).resolve().parent.parent.parent)) diff --git a/tests/gateway/test_feishu.py b/tests/gateway/test_feishu.py index 75f61923956..b6472b04e00 100644 --- a/tests/gateway/test_feishu.py +++ b/tests/gateway/test_feishu.py @@ -3126,8 +3126,6 @@ class TestWebhookSecurity(unittest.TestCase): def test_signature_valid_passes(self): import hashlib - from gateway.platforms.feishu import FeishuAdapter - from gateway.config import PlatformConfig encrypt_key = "test_secret" adapter = self._make_adapter(encrypt_key) diff --git a/tests/gateway/test_feishu_bot_admission.py b/tests/gateway/test_feishu_bot_admission.py index 5ccc386d83e..2d71ad06de1 100644 --- a/tests/gateway/test_feishu_bot_admission.py +++ b/tests/gateway/test_feishu_bot_admission.py @@ -3,7 +3,6 @@ from __future__ import annotations from types import SimpleNamespace -from typing import Any import pytest diff --git a/tests/gateway/test_feishu_comment.py b/tests/gateway/test_feishu_comment.py index 0a09481ac8c..6241de6f86e 100644 --- a/tests/gateway/test_feishu_comment.py +++ b/tests/gateway/test_feishu_comment.py @@ -1,7 +1,6 @@ """Tests for feishu_comment — event filtering, access control integration, wiki reverse lookup.""" import asyncio -import json import unittest from types import SimpleNamespace from unittest.mock import AsyncMock, Mock, patch diff --git a/tests/gateway/test_fresh_reset_skill_injection.py b/tests/gateway/test_fresh_reset_skill_injection.py index 885dd0f15d6..1f7b4f1a32f 100644 --- a/tests/gateway/test_fresh_reset_skill_injection.py +++ b/tests/gateway/test_fresh_reset_skill_injection.py @@ -25,7 +25,6 @@ a "Session automatically reset due to inactivity" user-facing notice and a context-note prepend into the agent's prompt — both wrong for an explicit /new or /reset. """ -import pytest from gateway.config import GatewayConfig, Platform from gateway.session import SessionEntry, SessionSource, SessionStore diff --git a/tests/gateway/test_gateway_inactivity_timeout.py b/tests/gateway/test_gateway_inactivity_timeout.py index 28e22b05797..2c57bf6ed32 100644 --- a/tests/gateway/test_gateway_inactivity_timeout.py +++ b/tests/gateway/test_gateway_inactivity_timeout.py @@ -14,9 +14,7 @@ import os import sys import time from pathlib import Path -from unittest.mock import MagicMock, patch -import pytest sys.path.insert(0, str(Path(__file__).parent.parent.parent)) diff --git a/tests/gateway/test_hooks.py b/tests/gateway/test_hooks.py index ac9e51919c4..a614f9cbe0e 100644 --- a/tests/gateway/test_hooks.py +++ b/tests/gateway/test_hooks.py @@ -1,7 +1,5 @@ """Tests for gateway/hooks.py — event hook system.""" -import asyncio -from pathlib import Path from unittest.mock import patch import pytest diff --git a/tests/gateway/test_internal_event_bypass_pairing.py b/tests/gateway/test_internal_event_bypass_pairing.py index 88788425387..f0348a759da 100644 --- a/tests/gateway/test_internal_event_bypass_pairing.py +++ b/tests/gateway/test_internal_event_bypass_pairing.py @@ -9,7 +9,7 @@ pairing code to the chat. import asyncio from types import SimpleNamespace -from unittest.mock import AsyncMock, patch +from unittest.mock import AsyncMock import pytest diff --git a/tests/gateway/test_irc_adapter.py b/tests/gateway/test_irc_adapter.py index 246dbfdf0ec..1320152c637 100644 --- a/tests/gateway/test_irc_adapter.py +++ b/tests/gateway/test_irc_adapter.py @@ -1,11 +1,8 @@ """Tests for the IRC platform adapter plugin.""" import asyncio -import os -import sys import pytest -from pathlib import Path -from unittest.mock import AsyncMock, MagicMock, patch +from unittest.mock import AsyncMock, MagicMock from tests.gateway._plugin_adapter_loader import load_plugin_adapter diff --git a/tests/gateway/test_kanban_notifier.py b/tests/gateway/test_kanban_notifier.py index 8e85f045037..9dd5aa3749b 100644 --- a/tests/gateway/test_kanban_notifier.py +++ b/tests/gateway/test_kanban_notifier.py @@ -1,7 +1,6 @@ import asyncio from pathlib import Path -import pytest from gateway.config import Platform from gateway.run import GatewayRunner diff --git a/tests/gateway/test_line_plugin.py b/tests/gateway/test_line_plugin.py index e7fd2cf9946..4f42c0f08da 100644 --- a/tests/gateway/test_line_plugin.py +++ b/tests/gateway/test_line_plugin.py @@ -19,8 +19,7 @@ import hashlib import hmac import base64 import json -import os -from unittest.mock import AsyncMock, MagicMock, patch +from unittest.mock import AsyncMock, MagicMock import pytest diff --git a/tests/gateway/test_load_transcript_db_only.py b/tests/gateway/test_load_transcript_db_only.py index 2425e495a6b..6d9025a4edc 100644 --- a/tests/gateway/test_load_transcript_db_only.py +++ b/tests/gateway/test_load_transcript_db_only.py @@ -1,7 +1,5 @@ """Verify load_transcript returns SQLite messages without any JSONL file.""" -from pathlib import Path -import pytest from gateway.session import SessionStore from gateway.config import GatewayConfig diff --git a/tests/gateway/test_matrix.py b/tests/gateway/test_matrix.py index c7c03b1a8b1..c0294b41ec9 100644 --- a/tests/gateway/test_matrix.py +++ b/tests/gateway/test_matrix.py @@ -1,9 +1,6 @@ """Tests for Matrix platform adapter (mautrix-python backend).""" import asyncio -import json -import re import sys -import time import types import pytest from unittest.mock import MagicMock, patch, AsyncMock @@ -974,7 +971,6 @@ class TestDeviceKeyReVerification: mock_olm.account.identity_keys = {"ed25519": "local_new_key"} mock_olm.share_keys = AsyncMock() - from gateway.platforms.matrix import MatrixAdapter result = await adapter._verify_device_keys_on_server(mock_client, mock_olm) assert result is False @@ -986,7 +982,7 @@ class TestMatrixE2EEHardFail: @pytest.mark.asyncio async def test_connect_fails_when_encryption_true_but_no_e2ee_deps(self): - from gateway.platforms.matrix import MatrixAdapter, _check_e2ee_deps + from gateway.platforms.matrix import MatrixAdapter config = PlatformConfig( enabled=True, @@ -1208,7 +1204,6 @@ class TestMatrixPasswordLoginDeviceId: fake_mautrix_mods["mautrix.client"].Client = MagicMock(return_value=mock_client) - from gateway.platforms import matrix as matrix_mod with patch.dict("sys.modules", fake_mautrix_mods): with patch.object(adapter, "_refresh_dm_cache", AsyncMock()): with patch.object(adapter, "_sync_loop", AsyncMock(return_value=None)): diff --git a/tests/gateway/test_matrix_mention.py b/tests/gateway/test_matrix_mention.py index 6c34dbce892..634c1c765f9 100644 --- a/tests/gateway/test_matrix_mention.py +++ b/tests/gateway/test_matrix_mention.py @@ -1,7 +1,6 @@ """Tests for Matrix require-mention gating and auto-thread features.""" import json -import sys import time from types import SimpleNamespace from unittest.mock import AsyncMock, MagicMock, patch diff --git a/tests/gateway/test_matrix_voice.py b/tests/gateway/test_matrix_voice.py index 3b3e08d1422..51bf150b29b 100644 --- a/tests/gateway/test_matrix_voice.py +++ b/tests/gateway/test_matrix_voice.py @@ -2,7 +2,6 @@ Updated for the mautrix-python SDK (no more matrix-nio / nio imports). """ -import io import os import tempfile import types diff --git a/tests/gateway/test_media_download_retry.py b/tests/gateway/test_media_download_retry.py index 5991b85e4eb..bb45061f842 100644 --- a/tests/gateway/test_media_download_retry.py +++ b/tests/gateway/test_media_download_retry.py @@ -536,7 +536,7 @@ import gateway.platforms.slack as _slack_mod # noqa: E402 _slack_mod.SLACK_AVAILABLE = True from gateway.platforms.slack import SlackAdapter # noqa: E402 -from gateway.config import Platform, PlatformConfig # noqa: E402 +from gateway.config import PlatformConfig # noqa: E402 def _make_slack_adapter(): diff --git a/tests/gateway/test_message_deduplicator.py b/tests/gateway/test_message_deduplicator.py index 4a140f2761b..e6470075284 100644 --- a/tests/gateway/test_message_deduplicator.py +++ b/tests/gateway/test_message_deduplicator.py @@ -10,7 +10,6 @@ the past, the entry is treated as expired and the message is allowed through. """ import time -from unittest.mock import patch from gateway.platforms.helpers import MessageDeduplicator diff --git a/tests/gateway/test_mirror.py b/tests/gateway/test_mirror.py index 918e0bff6c7..88183d0079b 100644 --- a/tests/gateway/test_mirror.py +++ b/tests/gateway/test_mirror.py @@ -1,7 +1,6 @@ """Tests for gateway/mirror.py — session mirroring.""" import json -from pathlib import Path from unittest.mock import patch, MagicMock import gateway.mirror as mirror_mod diff --git a/tests/gateway/test_model_switch_persistence.py b/tests/gateway/test_model_switch_persistence.py index 07fa5d5f435..29adf19e6f8 100644 --- a/tests/gateway/test_model_switch_persistence.py +++ b/tests/gateway/test_model_switch_persistence.py @@ -15,7 +15,6 @@ from datetime import datetime from types import SimpleNamespace from unittest.mock import AsyncMock, MagicMock -import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig from gateway.session import SessionEntry, SessionSource, build_session_key diff --git a/tests/gateway/test_msgraph_webhook.py b/tests/gateway/test_msgraph_webhook.py index d23f5dca50b..caa141c6a44 100644 --- a/tests/gateway/test_msgraph_webhook.py +++ b/tests/gateway/test_msgraph_webhook.py @@ -1,7 +1,6 @@ """Tests for the Microsoft Graph webhook adapter.""" import asyncio -import json import pytest diff --git a/tests/gateway/test_ntfy_plugin.py b/tests/gateway/test_ntfy_plugin.py index 40cf148de44..f2f24ae4aa8 100644 --- a/tests/gateway/test_ntfy_plugin.py +++ b/tests/gateway/test_ntfy_plugin.py @@ -15,7 +15,6 @@ the ``platform_registry``. from __future__ import annotations import asyncio -import os from unittest.mock import AsyncMock, MagicMock, patch import pytest diff --git a/tests/gateway/test_pairing.py b/tests/gateway/test_pairing.py index 0bff131ed1a..74e718f181a 100644 --- a/tests/gateway/test_pairing.py +++ b/tests/gateway/test_pairing.py @@ -4,7 +4,6 @@ import json import os import sys import time -from pathlib import Path from unittest.mock import patch import pytest @@ -17,7 +16,6 @@ from gateway.pairing import ( RATE_LIMIT_SECONDS, MAX_PENDING_PER_PLATFORM, MAX_FAILED_ATTEMPTS, - LOCKOUT_SECONDS, _secure_write, ) diff --git a/tests/gateway/test_planned_stop_watcher.py b/tests/gateway/test_planned_stop_watcher.py index 8887d122a78..bee5802b803 100644 --- a/tests/gateway/test_planned_stop_watcher.py +++ b/tests/gateway/test_planned_stop_watcher.py @@ -14,10 +14,8 @@ See issue #33778 for the original Windows session-loss bug report. import asyncio import threading import time -from types import SimpleNamespace from unittest.mock import MagicMock -import pytest from gateway.run import _run_planned_stop_watcher diff --git a/tests/gateway/test_platform_base.py b/tests/gateway/test_platform_base.py index 8be8feb2a46..34d94c06f58 100644 --- a/tests/gateway/test_platform_base.py +++ b/tests/gateway/test_platform_base.py @@ -10,7 +10,6 @@ from gateway.platforms.base import ( BasePlatformAdapter, GATEWAY_SECRET_CAPTURE_UNSUPPORTED_MESSAGE, MessageEvent, - MessageType, safe_url_for_log, utf16_len, _prefix_within_utf16_limit, diff --git a/tests/gateway/test_platform_http_client_limits.py b/tests/gateway/test_platform_http_client_limits.py index fe613fb1f08..074a6d52ec3 100644 --- a/tests/gateway/test_platform_http_client_limits.py +++ b/tests/gateway/test_platform_http_client_limits.py @@ -12,7 +12,6 @@ behaviour is only observable at runtime under load. from __future__ import annotations -import os import pytest diff --git a/tests/gateway/test_platform_reconnect.py b/tests/gateway/test_platform_reconnect.py index e4362a02562..1a5a35a42e7 100644 --- a/tests/gateway/test_platform_reconnect.py +++ b/tests/gateway/test_platform_reconnect.py @@ -7,7 +7,7 @@ from unittest.mock import AsyncMock, MagicMock, patch import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import BasePlatformAdapter, MessageEvent, SendResult +from gateway.platforms.base import BasePlatformAdapter, SendResult from gateway.run import GatewayRunner diff --git a/tests/gateway/test_platform_registry.py b/tests/gateway/test_platform_registry.py index 9ca80fe8a1f..881ec1f3dba 100644 --- a/tests/gateway/test_platform_registry.py +++ b/tests/gateway/test_platform_registry.py @@ -2,11 +2,10 @@ import os import pytest -from unittest.mock import MagicMock, patch -from dataclasses import dataclass +from unittest.mock import MagicMock -from gateway.platform_registry import PlatformRegistry, PlatformEntry, platform_registry -from gateway.config import Platform, PlatformConfig, GatewayConfig +from gateway.platform_registry import PlatformRegistry, PlatformEntry +from gateway.config import Platform, GatewayConfig # ── Platform enum dynamic members ───────────────────────────────────────── diff --git a/tests/gateway/test_proxy_mode.py b/tests/gateway/test_proxy_mode.py index 7ed6a19cb22..0c7fa80a0ba 100644 --- a/tests/gateway/test_proxy_mode.py +++ b/tests/gateway/test_proxy_mode.py @@ -1,8 +1,5 @@ """Tests for gateway proxy mode — forwarding messages to a remote API server.""" -import asyncio -import json -import os from unittest.mock import AsyncMock, MagicMock, patch import pytest diff --git a/tests/gateway/test_qqbot.py b/tests/gateway/test_qqbot.py index bdcb4c9e8df..6516a25f8b2 100644 --- a/tests/gateway/test_qqbot.py +++ b/tests/gateway/test_qqbot.py @@ -1,15 +1,13 @@ """Tests for the QQ Bot platform adapter.""" import asyncio -import json import os -import sys from types import SimpleNamespace from unittest import mock import pytest -from gateway.config import Platform, PlatformConfig +from gateway.config import PlatformConfig # --------------------------------------------------------------------------- diff --git a/tests/gateway/test_queue_consumption.py b/tests/gateway/test_queue_consumption.py index 9bb4d0aac36..178d1965af9 100644 --- a/tests/gateway/test_queue_consumption.py +++ b/tests/gateway/test_queue_consumption.py @@ -6,9 +6,8 @@ after the agent finishes its current task — not silently dropped. """ import asyncio -from unittest.mock import AsyncMock, MagicMock, patch +from unittest.mock import MagicMock -import pytest from gateway.run import _dequeue_pending_event from gateway.platforms.base import ( diff --git a/tests/gateway/test_replay_entry_fields.py b/tests/gateway/test_replay_entry_fields.py index 4858cf62522..c0891d3721f 100644 --- a/tests/gateway/test_replay_entry_fields.py +++ b/tests/gateway/test_replay_entry_fields.py @@ -16,7 +16,6 @@ These tests pin the expanded whitelist so it doesn't regress. """ from __future__ import annotations -import pytest from gateway.run import _ASSISTANT_REPLAY_FIELDS, _build_replay_entry diff --git a/tests/gateway/test_restart_notification.py b/tests/gateway/test_restart_notification.py index 3d5d5ee9557..e7a931f8f8a 100644 --- a/tests/gateway/test_restart_notification.py +++ b/tests/gateway/test_restart_notification.py @@ -1,6 +1,5 @@ """Tests for /restart notification — the gateway notifies the requester on comeback.""" -import asyncio import json from pathlib import Path from unittest.mock import AsyncMock, MagicMock diff --git a/tests/gateway/test_restart_redelivery_dedup.py b/tests/gateway/test_restart_redelivery_dedup.py index aa4e4330caf..88cb0223d07 100644 --- a/tests/gateway/test_restart_redelivery_dedup.py +++ b/tests/gateway/test_restart_redelivery_dedup.py @@ -5,7 +5,6 @@ with a network error, Telegram re-delivers the `/restart` message to the new gateway process. Without a dedup guard, the new gateway would process `/restart` again and immediately restart — a self-perpetuating loop. """ -import asyncio import json import time from unittest.mock import MagicMock diff --git a/tests/gateway/test_restart_resume_pending.py b/tests/gateway/test_restart_resume_pending.py index 996153239fc..346a6ad1ad4 100644 --- a/tests/gateway/test_restart_resume_pending.py +++ b/tests/gateway/test_restart_resume_pending.py @@ -32,7 +32,7 @@ from unittest.mock import AsyncMock, MagicMock, patch import pytest -from gateway.config import GatewayConfig, HomeChannel, Platform, PlatformConfig +from gateway.config import GatewayConfig, HomeChannel, Platform from gateway.platforms.base import MessageEvent, MessageType, SendResult from gateway.run import ( _auto_continue_freshness_window, diff --git a/tests/gateway/test_run_progress_interrupt.py b/tests/gateway/test_run_progress_interrupt.py index 23969677e06..cc25b8db868 100644 --- a/tests/gateway/test_run_progress_interrupt.py +++ b/tests/gateway/test_run_progress_interrupt.py @@ -8,7 +8,6 @@ of tool-progress bubbles for calls that were already parsed from the LLM response — making the interrupt feel ignored. """ -import asyncio import importlib import sys import time diff --git a/tests/gateway/test_runner_startup_failures.py b/tests/gateway/test_runner_startup_failures.py index b82062e4090..3fbf3708852 100644 --- a/tests/gateway/test_runner_startup_failures.py +++ b/tests/gateway/test_runner_startup_failures.py @@ -248,7 +248,7 @@ async def test_start_gateway_replace_writes_takeover_marker_before_sigterm( (tmp_path / ".gateway-takeover.json").exists() is False # not yet ) # Actually write the marker so we can verify cleanup later - from gateway.status import _get_takeover_marker_path, _write_json_file, _get_process_start_time + from gateway.status import _get_takeover_marker_path, _write_json_file _write_json_file(_get_takeover_marker_path(), { "target_pid": target_pid, "target_start_time": 0, diff --git a/tests/gateway/test_send_image_file.py b/tests/gateway/test_send_image_file.py index b769d2be9fb..9cbf48fd0d7 100644 --- a/tests/gateway/test_send_image_file.py +++ b/tests/gateway/test_send_image_file.py @@ -14,7 +14,7 @@ from unittest.mock import AsyncMock, MagicMock, patch import pytest from gateway.config import PlatformConfig -from gateway.platforms.base import BasePlatformAdapter, SendResult +from gateway.platforms.base import BasePlatformAdapter def _run(coro): diff --git a/tests/gateway/test_send_multiple_images.py b/tests/gateway/test_send_multiple_images.py index 6bff0f09a36..5fab55c4a70 100644 --- a/tests/gateway/test_send_multiple_images.py +++ b/tests/gateway/test_send_multiple_images.py @@ -13,7 +13,6 @@ Signal's native implementation is covered by test_signal.py. """ import asyncio -import os import sys from unittest.mock import AsyncMock, MagicMock, patch diff --git a/tests/gateway/test_session_api.py b/tests/gateway/test_session_api.py index a2d00d9c8c7..5b06ffd55ce 100644 --- a/tests/gateway/test_session_api.py +++ b/tests/gateway/test_session_api.py @@ -1,6 +1,5 @@ """Focused tests for API server session-control endpoints.""" -import asyncio from unittest.mock import AsyncMock, patch import pytest diff --git a/tests/gateway/test_session_dm_thread_seeding.py b/tests/gateway/test_session_dm_thread_seeding.py index 415e953baa2..bcb1e7fee52 100644 --- a/tests/gateway/test_session_dm_thread_seeding.py +++ b/tests/gateway/test_session_dm_thread_seeding.py @@ -15,10 +15,9 @@ Covers: """ import pytest -from unittest.mock import patch from gateway.config import Platform, GatewayConfig -from gateway.session import SessionSource, SessionStore, build_session_key +from gateway.session import SessionSource, SessionStore @pytest.fixture() diff --git a/tests/gateway/test_session_hygiene.py b/tests/gateway/test_session_hygiene.py index fb8b273f411..b54f588cb10 100644 --- a/tests/gateway/test_session_hygiene.py +++ b/tests/gateway/test_session_hygiene.py @@ -13,7 +13,7 @@ import sys import types from datetime import datetime from types import SimpleNamespace -from unittest.mock import patch, MagicMock, AsyncMock +from unittest.mock import MagicMock, AsyncMock import pytest diff --git a/tests/gateway/test_session_info.py b/tests/gateway/test_session_info.py index d8c65305f7b..ec05b31b735 100644 --- a/tests/gateway/test_session_info.py +++ b/tests/gateway/test_session_info.py @@ -1,8 +1,7 @@ """Tests for GatewayRunner._format_session_info — session config surfacing.""" import pytest -from unittest.mock import patch, MagicMock -from pathlib import Path +from unittest.mock import patch from gateway.run import GatewayRunner diff --git a/tests/gateway/test_session_reset_notify.py b/tests/gateway/test_session_reset_notify.py index a4e9d71d0f8..c73ed640ccd 100644 --- a/tests/gateway/test_session_reset_notify.py +++ b/tests/gateway/test_session_reset_notify.py @@ -8,14 +8,11 @@ Verifies that: """ from datetime import datetime, timedelta -from unittest.mock import MagicMock -import pytest from gateway.config import ( GatewayConfig, Platform, - PlatformConfig, SessionResetPolicy, ) from gateway.session import SessionEntry, SessionSource, SessionStore diff --git a/tests/gateway/test_session_split_brain_11016.py b/tests/gateway/test_session_split_brain_11016.py index 0b2972ac173..85fe274ab2e 100644 --- a/tests/gateway/test_session_split_brain_11016.py +++ b/tests/gateway/test_session_split_brain_11016.py @@ -17,7 +17,7 @@ Covers three layers of the fix: """ import asyncio -from unittest.mock import AsyncMock, MagicMock, patch +from unittest.mock import MagicMock import pytest @@ -27,7 +27,7 @@ from gateway.platforms.base import ( MessageEvent, MessageType, ) -from gateway.run import GatewayRunner, _AGENT_PENDING_SENTINEL +from gateway.run import GatewayRunner from gateway.session import SessionSource, build_session_key diff --git a/tests/gateway/test_session_state_cleanup.py b/tests/gateway/test_session_state_cleanup.py index 3c708736c3b..ffbb465b7aa 100644 --- a/tests/gateway/test_session_state_cleanup.py +++ b/tests/gateway/test_session_state_cleanup.py @@ -19,7 +19,6 @@ leaving WAL locks in place until Python actually exited. import threading from unittest.mock import MagicMock -import pytest def _make_runner(): diff --git a/tests/gateway/test_session_store_prune.py b/tests/gateway/test_session_store_prune.py index 34fa21e25a8..d6af52edf45 100644 --- a/tests/gateway/test_session_store_prune.py +++ b/tests/gateway/test_session_store_prune.py @@ -19,7 +19,6 @@ import threading from datetime import datetime, timedelta from unittest.mock import patch -import pytest from gateway.config import GatewayConfig, Platform, SessionResetPolicy from gateway.session import SessionEntry, SessionStore diff --git a/tests/gateway/test_shutdown_cache_cleanup.py b/tests/gateway/test_shutdown_cache_cleanup.py index 82970d20c50..fd3f1e9b952 100644 --- a/tests/gateway/test_shutdown_cache_cleanup.py +++ b/tests/gateway/test_shutdown_cache_cleanup.py @@ -12,7 +12,7 @@ The fix adds an explicit sweep of ``_agent_cache`` after import asyncio import threading from collections import OrderedDict -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock import pytest diff --git a/tests/gateway/test_signal.py b/tests/gateway/test_signal.py index 7f34698f027..a5e225b759b 100644 --- a/tests/gateway/test_signal.py +++ b/tests/gateway/test_signal.py @@ -1,7 +1,6 @@ """Tests for Signal messenger platform adapter.""" import asyncio import base64 -import json import pytest from pathlib import Path from unittest.mock import MagicMock, patch, AsyncMock diff --git a/tests/gateway/test_signal_format.py b/tests/gateway/test_signal_format.py index ef50f62fd0a..0050a980f59 100644 --- a/tests/gateway/test_signal_format.py +++ b/tests/gateway/test_signal_format.py @@ -430,7 +430,6 @@ class TestSignalStreamingPatch: """send() returns message_id=None so stream consumer uses no-edit path.""" monkeypatch.setenv("SIGNAL_GROUP_ALLOWED_USERS", "") from gateway.platforms.signal import SignalAdapter - from gateway.config import PlatformConfig config = PlatformConfig(enabled=True) config.extra = { diff --git a/tests/gateway/test_signal_rate_limit.py b/tests/gateway/test_signal_rate_limit.py index 963f8b9303b..d2111cb3d28 100644 --- a/tests/gateway/test_signal_rate_limit.py +++ b/tests/gateway/test_signal_rate_limit.py @@ -1,11 +1,9 @@ """Tests for the SignalAttachmentScheduler token-bucket simulator.""" import asyncio -import time import pytest from gateway.platforms.signal_rate_limit import ( - SIGNAL_MAX_ATTACHMENTS_PER_MSG, SIGNAL_RATE_LIMIT_BUCKET_CAPACITY, SIGNAL_RATE_LIMIT_DEFAULT_RETRY_AFTER, SignalAttachmentScheduler, diff --git a/tests/gateway/test_simplex_plugin.py b/tests/gateway/test_simplex_plugin.py index 0b1b1b21a85..1048168aa6e 100644 --- a/tests/gateway/test_simplex_plugin.py +++ b/tests/gateway/test_simplex_plugin.py @@ -8,7 +8,6 @@ sibling platform-plugin tests on the same xdist worker. from __future__ import annotations import json -import os from unittest.mock import AsyncMock, MagicMock import pytest diff --git a/tests/gateway/test_slack.py b/tests/gateway/test_slack.py index bc09279eec4..830b0e14f07 100644 --- a/tests/gateway/test_slack.py +++ b/tests/gateway/test_slack.py @@ -19,8 +19,6 @@ from gateway.config import Platform, PlatformConfig from gateway.platforms.base import ( MessageEvent, MessageType, - SendResult, - SUPPORTED_DOCUMENT_TYPES, is_host_excluded_by_no_proxy, ) @@ -1834,8 +1832,7 @@ class TestReactions: assert "1234567890.000001" in adapter._reacting_message_ids # Simulate the base class calling on_processing_start - from gateway.platforms.base import MessageEvent, MessageType, SessionSource - from gateway.config import Platform + from gateway.platforms.base import MessageType, SessionSource source = SessionSource( platform=Platform.SLACK, chat_id="C123", @@ -1874,8 +1871,7 @@ class TestReactions: adapter._app.client.reactions_add = AsyncMock() adapter._app.client.reactions_remove = AsyncMock() - from gateway.platforms.base import MessageEvent, MessageType, SessionSource, ProcessingOutcome - from gateway.config import Platform + from gateway.platforms.base import MessageType, SessionSource, ProcessingOutcome source = SessionSource( platform=Platform.SLACK, chat_id="C123", @@ -1944,8 +1940,7 @@ class TestReactions: assert "1234567890.000004" not in adapter._reacting_message_ids # Hooks should also be no-ops when disabled - from gateway.platforms.base import MessageEvent, MessageType, SessionSource, ProcessingOutcome - from gateway.config import Platform + from gateway.platforms.base import MessageType, SessionSource, ProcessingOutcome source = SessionSource( platform=Platform.SLACK, chat_id="C123", diff --git a/tests/gateway/test_slack_approval_buttons.py b/tests/gateway/test_slack_approval_buttons.py index bc12d0072bd..16f991118b8 100644 --- a/tests/gateway/test_slack_approval_buttons.py +++ b/tests/gateway/test_slack_approval_buttons.py @@ -1,7 +1,5 @@ """Tests for Slack Block Kit approval buttons and thread context fetching.""" -import asyncio -import os import sys from pathlib import Path from unittest.mock import AsyncMock, MagicMock, patch @@ -44,7 +42,7 @@ def _ensure_slack_mock(): _ensure_slack_mock() from gateway.platforms.slack import SlackAdapter -from gateway.config import Platform, PlatformConfig +from gateway.config import PlatformConfig def _make_adapter(): diff --git a/tests/gateway/test_slash_access.py b/tests/gateway/test_slash_access.py index 5e21ac8b610..c939a446c9e 100644 --- a/tests/gateway/test_slash_access.py +++ b/tests/gateway/test_slash_access.py @@ -8,7 +8,6 @@ from __future__ import annotations from gateway.config import GatewayConfig, Platform, PlatformConfig from gateway.session import SessionSource from gateway.slash_access import ( - SlashAccessPolicy, policy_for_source, policy_from_extra, ) diff --git a/tests/gateway/test_slash_access_dispatch.py b/tests/gateway/test_slash_access_dispatch.py index 1e26c93e0eb..1a597cf688f 100644 --- a/tests/gateway/test_slash_access_dispatch.py +++ b/tests/gateway/test_slash_access_dispatch.py @@ -337,7 +337,6 @@ async def test_running_agent_fastpath_blocks_non_admin_command(): ) src = _make_source(user_id="999") # Mark the session as having an in-flight agent so the fast-path runs. - from gateway.session import build_session_key sk = build_session_key(src) runner._running_agents[sk] = MagicMock() runner._running_agents_ts[sk] = 0 # not stale (epoch + small delta on this machine) @@ -361,7 +360,6 @@ async def test_running_agent_fastpath_allows_admin_command(): } ) src = _make_source(user_id="111") # admin - from gateway.session import build_session_key sk = build_session_key(src) runner._running_agents[sk] = MagicMock() runner._running_agents_ts[sk] = 0 @@ -384,7 +382,6 @@ async def test_running_agent_fastpath_status_always_works(): } ) src = _make_source(user_id="999") # non-admin - from gateway.session import build_session_key sk = build_session_key(src) runner._running_agents[sk] = MagicMock() runner._running_agents_ts[sk] = 0 diff --git a/tests/gateway/test_sms.py b/tests/gateway/test_sms.py index e3ec86d90af..8d8b73614aa 100644 --- a/tests/gateway/test_sms.py +++ b/tests/gateway/test_sms.py @@ -12,7 +12,7 @@ from unittest.mock import AsyncMock, MagicMock, patch import pytest -from gateway.config import Platform, PlatformConfig, HomeChannel +from gateway.config import Platform, PlatformConfig # ── Config loading ────────────────────────────────────────────────── diff --git a/tests/gateway/test_sse_agent_cancel.py b/tests/gateway/test_sse_agent_cancel.py index 6b5306fbe6e..2958a5b3e8c 100644 --- a/tests/gateway/test_sse_agent_cancel.py +++ b/tests/gateway/test_sse_agent_cancel.py @@ -7,11 +7,9 @@ task wrapper is cancelled. """ import asyncio -import json import queue from unittest.mock import AsyncMock, MagicMock, patch -import pytest # --------------------------------------------------------------------------- diff --git a/tests/gateway/test_ssl_certs.py b/tests/gateway/test_ssl_certs.py index f98eb03a6cd..2fc34ea9d5c 100644 --- a/tests/gateway/test_ssl_certs.py +++ b/tests/gateway/test_ssl_certs.py @@ -1,6 +1,5 @@ """Tests for SSL certificate auto-detection in gateway/run.py.""" -import importlib import os from unittest.mock import patch, MagicMock diff --git a/tests/gateway/test_status_command.py b/tests/gateway/test_status_command.py index d8504370a5f..01222597224 100644 --- a/tests/gateway/test_status_command.py +++ b/tests/gateway/test_status_command.py @@ -495,7 +495,7 @@ async def test_status_command_bypasses_active_session_guard(): import asyncio from gateway.platforms.base import BasePlatformAdapter, MessageEvent, MessageType from gateway.session import build_session_key - from gateway.config import Platform, PlatformConfig, GatewayConfig + from gateway.config import Platform, PlatformConfig source = _make_source() session_key = build_session_key(source) diff --git a/tests/gateway/test_step_callback_compat.py b/tests/gateway/test_step_callback_compat.py index cdfc3fb04ac..3111f011a52 100644 --- a/tests/gateway/test_step_callback_compat.py +++ b/tests/gateway/test_step_callback_compat.py @@ -6,9 +6,7 @@ while also providing the enriched ``tools`` list with results. """ import asyncio -from unittest.mock import AsyncMock, MagicMock, patch -import pytest class TestStepCallbackNormalization: diff --git a/tests/gateway/test_sticker_cache.py b/tests/gateway/test_sticker_cache.py index a8fc9121954..9223a11e17d 100644 --- a/tests/gateway/test_sticker_cache.py +++ b/tests/gateway/test_sticker_cache.py @@ -1,7 +1,5 @@ """Tests for gateway/sticker_cache.py — sticker description cache.""" -import json -import time from unittest.mock import patch from gateway.sticker_cache import ( @@ -11,7 +9,6 @@ from gateway.sticker_cache import ( cache_sticker_description, build_sticker_injection, build_animated_sticker_injection, - STICKER_VISION_PROMPT, ) diff --git a/tests/gateway/test_stream_consumer_thread_routing.py b/tests/gateway/test_stream_consumer_thread_routing.py index 80477574d87..ec4611abfa3 100644 --- a/tests/gateway/test_stream_consumer_thread_routing.py +++ b/tests/gateway/test_stream_consumer_thread_routing.py @@ -6,15 +6,13 @@ the main group chat. Covers: #6969, #9916, #7355 """ -import asyncio -from unittest.mock import AsyncMock, MagicMock, patch +from unittest.mock import AsyncMock, MagicMock from types import SimpleNamespace import pytest from gateway.stream_consumer import ( GatewayStreamConsumer, - StreamConsumerConfig, ) diff --git a/tests/gateway/test_stuck_loop.py b/tests/gateway/test_stuck_loop.py index a26f29a2b57..31f9858869a 100644 --- a/tests/gateway/test_stuck_loop.py +++ b/tests/gateway/test_stuck_loop.py @@ -6,7 +6,6 @@ is auto-suspended on startup so the user gets a clean slate. """ import json -from pathlib import Path from unittest.mock import MagicMock import pytest diff --git a/tests/gateway/test_teams.py b/tests/gateway/test_teams.py index 6c7173fe931..b9f575ef9f5 100644 --- a/tests/gateway/test_teams.py +++ b/tests/gateway/test_teams.py @@ -1,13 +1,10 @@ """Tests for the Microsoft Teams platform adapter plugin.""" -import asyncio import json -import os import sys import types -from pathlib import Path from types import SimpleNamespace -from unittest.mock import AsyncMock, MagicMock, patch +from unittest.mock import AsyncMock, MagicMock import httpx import pytest diff --git a/tests/gateway/test_telegram_approval_buttons.py b/tests/gateway/test_telegram_approval_buttons.py index e2ca8566827..5810b87a59b 100644 --- a/tests/gateway/test_telegram_approval_buttons.py +++ b/tests/gateway/test_telegram_approval_buttons.py @@ -1,6 +1,5 @@ """Tests for Telegram inline keyboard approval buttons.""" -import asyncio import os import sys from pathlib import Path diff --git a/tests/gateway/test_telegram_audio_vs_voice.py b/tests/gateway/test_telegram_audio_vs_voice.py index d8ad38e299c..5af5cb920a7 100644 --- a/tests/gateway/test_telegram_audio_vs_voice.py +++ b/tests/gateway/test_telegram_audio_vs_voice.py @@ -12,7 +12,7 @@ These tests confirm that: 3. Mixed media lists (voice + audio) split correctly. """ -from unittest.mock import AsyncMock, MagicMock, patch +from unittest.mock import patch import pytest diff --git a/tests/gateway/test_telegram_caption_merge.py b/tests/gateway/test_telegram_caption_merge.py index 09cfd8c3d7e..f5d4390f483 100644 --- a/tests/gateway/test_telegram_caption_merge.py +++ b/tests/gateway/test_telegram_caption_merge.py @@ -1,6 +1,5 @@ """Tests for TelegramPlatform._merge_caption caption deduplication logic.""" -import pytest from gateway.platforms.telegram import TelegramAdapter diff --git a/tests/gateway/test_telegram_clarify_buttons.py b/tests/gateway/test_telegram_clarify_buttons.py index 56c0f9e60c4..729ee22359a 100644 --- a/tests/gateway/test_telegram_clarify_buttons.py +++ b/tests/gateway/test_telegram_clarify_buttons.py @@ -4,11 +4,9 @@ Mirrors test_telegram_approval_buttons.py for the new ``send_clarify`` and ``cl:`` callback dispatch added in feat/clarify-gateway-buttons. """ -import asyncio import os import sys from pathlib import Path -from types import SimpleNamespace from unittest.mock import AsyncMock, MagicMock, patch import pytest @@ -50,7 +48,7 @@ def _ensure_telegram_mock(): _ensure_telegram_mock() from gateway.platforms.telegram import TelegramAdapter -from gateway.config import Platform, PlatformConfig +from gateway.config import PlatformConfig def _make_adapter(extra=None): diff --git a/tests/gateway/test_telegram_documents.py b/tests/gateway/test_telegram_documents.py index 8b2e1943cc2..f4155107aa0 100644 --- a/tests/gateway/test_telegram_documents.py +++ b/tests/gateway/test_telegram_documents.py @@ -9,7 +9,6 @@ We mock the telegram module at import time to avoid collection errors. """ import asyncio -import importlib import os import sys from types import SimpleNamespace @@ -17,12 +16,11 @@ from unittest.mock import AsyncMock, MagicMock, patch import pytest -from gateway.config import Platform, PlatformConfig +from gateway.config import PlatformConfig from gateway.platforms.base import ( MessageEvent, MessageType, SendResult, - SUPPORTED_DOCUMENT_TYPES, SUPPORTED_VIDEO_TYPES, ) diff --git a/tests/gateway/test_telegram_photo_interrupts.py b/tests/gateway/test_telegram_photo_interrupts.py index e808e68dbe8..74fb8baa3e3 100644 --- a/tests/gateway/test_telegram_photo_interrupts.py +++ b/tests/gateway/test_telegram_photo_interrupts.py @@ -1,4 +1,3 @@ -import asyncio from unittest.mock import MagicMock import pytest diff --git a/tests/gateway/test_telegram_progress_edit_transient.py b/tests/gateway/test_telegram_progress_edit_transient.py index 22cd6605348..33df94a90bf 100644 --- a/tests/gateway/test_telegram_progress_edit_transient.py +++ b/tests/gateway/test_telegram_progress_edit_transient.py @@ -17,8 +17,6 @@ Two layers are tested: from __future__ import annotations -import asyncio -from unittest.mock import AsyncMock import pytest diff --git a/tests/gateway/test_telegram_send_path_health.py b/tests/gateway/test_telegram_send_path_health.py index 940633224e4..05972bdba43 100644 --- a/tests/gateway/test_telegram_send_path_health.py +++ b/tests/gateway/test_telegram_send_path_health.py @@ -6,7 +6,6 @@ but nothing reaches the recipient. ``_send_path_degraded`` short-circuits ``send()`` so cron's live-adapter branch falls through to standalone HTTP. """ import sys -import types from unittest.mock import AsyncMock, MagicMock, patch import pytest diff --git a/tests/gateway/test_telegram_text_batch_perf.py b/tests/gateway/test_telegram_text_batch_perf.py index 518dee24604..194dd0d3ffb 100644 --- a/tests/gateway/test_telegram_text_batch_perf.py +++ b/tests/gateway/test_telegram_text_batch_perf.py @@ -13,8 +13,6 @@ or out-of-bounds values that could break asyncio.sleep(). from __future__ import annotations import math -import os -from unittest.mock import MagicMock import pytest diff --git a/tests/gateway/test_telegram_text_batching.py b/tests/gateway/test_telegram_text_batching.py index 4dd99f780fb..5cd45190067 100644 --- a/tests/gateway/test_telegram_text_batching.py +++ b/tests/gateway/test_telegram_text_batching.py @@ -7,7 +7,7 @@ from the same session and aggregate them before dispatching. import asyncio from types import SimpleNamespace -from unittest.mock import AsyncMock, MagicMock, patch +from unittest.mock import AsyncMock import pytest diff --git a/tests/gateway/test_telegram_topic_mode.py b/tests/gateway/test_telegram_topic_mode.py index 1941bb89e20..50f315ba7a8 100644 --- a/tests/gateway/test_telegram_topic_mode.py +++ b/tests/gateway/test_telegram_topic_mode.py @@ -960,7 +960,6 @@ def test_lobby_reminder_is_debounced_per_chat(tmp_path): def test_binding_survives_session_deletion_via_cascade(tmp_path): """Deleting a session with a topic binding must not raise FK errors.""" - import sqlite3 db = SessionDB(db_path=tmp_path / "state.db") db.enable_telegram_topic_mode(chat_id="208214988", user_id="208214988") db.create_session(session_id="sess-to-delete", source="telegram", user_id="208214988") @@ -988,7 +987,6 @@ def test_binding_survives_session_deletion_via_cascade(tmp_path): def test_migration_rebuilds_v1_binding_table_with_cascade_fk(tmp_path): """v1 → v2 migration rebuilds the bindings table when FK lacks ON DELETE CASCADE.""" - import sqlite3 db_path = tmp_path / "state.db" db = SessionDB(db_path=db_path) diff --git a/tests/gateway/test_telegram_webhook_secret.py b/tests/gateway/test_telegram_webhook_secret.py index 0f1e786367a..268a52e327e 100644 --- a/tests/gateway/test_telegram_webhook_secret.py +++ b/tests/gateway/test_telegram_webhook_secret.py @@ -13,7 +13,6 @@ import re import sys from pathlib import Path -import pytest _repo = str(Path(__file__).resolve().parents[2]) if _repo not in sys.path: diff --git a/tests/gateway/test_text_batching.py b/tests/gateway/test_text_batching.py index 7154ae4ae09..c0e7bf5d4b6 100644 --- a/tests/gateway/test_text_batching.py +++ b/tests/gateway/test_text_batching.py @@ -9,8 +9,7 @@ Telegram and Feishu. """ import asyncio -import os -from unittest.mock import AsyncMock, MagicMock, patch +from unittest.mock import AsyncMock import pytest diff --git a/tests/gateway/test_title_command.py b/tests/gateway/test_title_command.py index c09a2202f48..17b6fbe7102 100644 --- a/tests/gateway/test_title_command.py +++ b/tests/gateway/test_title_command.py @@ -4,9 +4,8 @@ Tests the _handle_title_command handler (set/show session titles) across all gateway messenger platforms. """ -import os from types import SimpleNamespace -from unittest.mock import AsyncMock, MagicMock, patch +from unittest.mock import AsyncMock, MagicMock import pytest diff --git a/tests/gateway/test_transcript_offset.py b/tests/gateway/test_transcript_offset.py index 7cbb519ee3a..23f5e72d182 100644 --- a/tests/gateway/test_transcript_offset.py +++ b/tests/gateway/test_transcript_offset.py @@ -12,7 +12,6 @@ messages. The fix adds ``history_offset`` (the filtered history length) to ``_run_agent``'s return dict and uses it for the slice. """ -import pytest from gateway.run import _preserve_queued_followup_history_offset diff --git a/tests/gateway/test_tts_media_routing.py b/tests/gateway/test_tts_media_routing.py index 82421785265..eaf9c592808 100644 --- a/tests/gateway/test_tts_media_routing.py +++ b/tests/gateway/test_tts_media_routing.py @@ -8,7 +8,7 @@ only renders as a voice bubble when explicitly flagged) and via """ from types import SimpleNamespace -from unittest.mock import AsyncMock, MagicMock +from unittest.mock import AsyncMock import pytest diff --git a/tests/gateway/test_update_command.py b/tests/gateway/test_update_command.py index aa6240aa5b5..154603898b3 100644 --- a/tests/gateway/test_update_command.py +++ b/tests/gateway/test_update_command.py @@ -5,7 +5,6 @@ the _send_update_notification startup hook (sends results after restart). """ import json -import os from pathlib import Path from unittest.mock import patch, MagicMock, AsyncMock @@ -74,7 +73,6 @@ class TestHandleUpdateCommand: pass # Simpler approach — mock at method level using a wrapper - from gateway.run import GatewayRunner runner = _make_runner() with patch("gateway.run._hermes_home", tmp_path): diff --git a/tests/gateway/test_update_streaming.py b/tests/gateway/test_update_streaming.py index eb0f0cfa890..e15e1c3f1f6 100644 --- a/tests/gateway/test_update_streaming.py +++ b/tests/gateway/test_update_streaming.py @@ -11,7 +11,6 @@ import json import os import time import asyncio -from pathlib import Path from unittest.mock import patch, MagicMock, AsyncMock import pytest diff --git a/tests/gateway/test_usage_command.py b/tests/gateway/test_usage_command.py index feced75b255..e0297b3e6d5 100644 --- a/tests/gateway/test_usage_command.py +++ b/tests/gateway/test_usage_command.py @@ -1,6 +1,5 @@ """Tests for gateway /usage command — agent cache lookup and output fields.""" -import asyncio import threading from unittest.mock import MagicMock, patch @@ -44,7 +43,7 @@ def _make_mock_agent(**overrides): def _make_runner(session_key, agent=None, cached_agent=None): """Build a bare GatewayRunner with just the fields _handle_usage_command needs.""" - from gateway.run import GatewayRunner, _AGENT_PENDING_SENTINEL + from gateway.run import GatewayRunner runner = object.__new__(GatewayRunner) runner._running_agents = {} diff --git a/tests/gateway/test_verbose_command.py b/tests/gateway/test_verbose_command.py index 055d61c262f..04399b1da50 100644 --- a/tests/gateway/test_verbose_command.py +++ b/tests/gateway/test_verbose_command.py @@ -1,6 +1,5 @@ """Tests for gateway /verbose command (config-gated tool progress cycling).""" -import asyncio from unittest.mock import AsyncMock, MagicMock import pytest diff --git a/tests/gateway/test_voice_command.py b/tests/gateway/test_voice_command.py index 160b35c6449..5066f4952f6 100644 --- a/tests/gateway/test_voice_command.py +++ b/tests/gateway/test_voice_command.py @@ -905,7 +905,6 @@ class TestVoiceChannelCommands: @pytest.mark.asyncio async def test_input_no_adapter(self, runner): """No Discord adapter — early return, no crash.""" - from gateway.config import Platform # No adapters set await runner._handle_voice_channel_input(111, 42, "Hello") @@ -1355,7 +1354,7 @@ class TestCallbackWiringOrder: def test_callback_set_before_join(self): """_handle_voice_channel_join wires callback before calling join.""" - import ast, inspect + import inspect from gateway.run import GatewayRunner source = inspect.getsource(GatewayRunner._handle_voice_channel_join) lines = source.split("\n") @@ -1490,7 +1489,7 @@ class TestAutoTtsEmptyTextGuard: def test_base_empty_check_in_source(self): """base.py must check speech_text is non-empty before calling TTS.""" - import ast, inspect + import inspect from gateway.platforms.base import BasePlatformAdapter source = inspect.getsource(BasePlatformAdapter._process_message_background) assert "if not speech_text" in source or "not speech_text" in source, ( @@ -2228,7 +2227,6 @@ class TestDisconnectVoiceCleanup: @pytest.mark.asyncio async def test_disconnect_clears_voice_state(self): - from unittest.mock import AsyncMock adapter = MagicMock() adapter._voice_clients = {111: MagicMock(), 222: MagicMock()} @@ -2665,7 +2663,7 @@ class TestVoiceTTSPlayback: def _call_should_reply(self, runner, voice_mode, msg_type, response="Hello", agent_msgs=None, already_sent=False): - from gateway.platforms.base import MessageType, MessageEvent, SessionSource + from gateway.platforms.base import MessageEvent, SessionSource from gateway.config import Platform runner._voice_mode["discord:ch1"] = voice_mode source = SessionSource( diff --git a/tests/gateway/test_voice_mode_platform_isolation.py b/tests/gateway/test_voice_mode_platform_isolation.py index 444c2d5789e..1cf45adbb8f 100644 --- a/tests/gateway/test_voice_mode_platform_isolation.py +++ b/tests/gateway/test_voice_mode_platform_isolation.py @@ -11,7 +11,6 @@ import tempfile from pathlib import Path from unittest.mock import MagicMock, patch -import pytest from gateway.config import Platform from gateway.run import GatewayRunner diff --git a/tests/gateway/test_webhook_adapter.py b/tests/gateway/test_webhook_adapter.py index 9cf61c3c3b5..606bd80e46e 100644 --- a/tests/gateway/test_webhook_adapter.py +++ b/tests/gateway/test_webhook_adapter.py @@ -27,7 +27,7 @@ from aiohttp import web from aiohttp.test_utils import TestClient, TestServer from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType, SendResult +from gateway.platforms.base import SendResult from gateway.platforms.webhook import ( WebhookAdapter, _INSECURE_NO_AUTH, diff --git a/tests/gateway/test_webhook_deliver_only.py b/tests/gateway/test_webhook_deliver_only.py index 3e40d95c6ee..987c396ee6f 100644 --- a/tests/gateway/test_webhook_deliver_only.py +++ b/tests/gateway/test_webhook_deliver_only.py @@ -14,8 +14,6 @@ Covers: """ import asyncio -import hashlib -import hmac import json from unittest.mock import AsyncMock, MagicMock, patch diff --git a/tests/gateway/test_webhook_dynamic_routes.py b/tests/gateway/test_webhook_dynamic_routes.py index 98c0db26492..31f7f0ac77a 100644 --- a/tests/gateway/test_webhook_dynamic_routes.py +++ b/tests/gateway/test_webhook_dynamic_routes.py @@ -1,9 +1,7 @@ """Tests for webhook adapter dynamic route loading.""" import json -import os import pytest -from pathlib import Path from gateway.config import PlatformConfig from gateway.platforms.webhook import ( diff --git a/tests/gateway/test_webhook_integration.py b/tests/gateway/test_webhook_integration.py index 5c6fe011110..9312ac0e999 100644 --- a/tests/gateway/test_webhook_integration.py +++ b/tests/gateway/test_webhook_integration.py @@ -19,11 +19,10 @@ from aiohttp.test_utils import TestClient, TestServer from gateway.config import ( GatewayConfig, - HomeChannel, Platform, PlatformConfig, ) -from gateway.platforms.base import MessageEvent, MessageType, SendResult +from gateway.platforms.base import MessageEvent, SendResult from gateway.platforms.webhook import WebhookAdapter, _INSECURE_NO_AUTH diff --git a/tests/gateway/test_wecom.py b/tests/gateway/test_wecom.py index 02d04daf64e..ad46a0bfb65 100644 --- a/tests/gateway/test_wecom.py +++ b/tests/gateway/test_wecom.py @@ -9,7 +9,7 @@ from unittest.mock import AsyncMock, MagicMock, patch import pytest -from gateway.config import Platform, PlatformConfig +from gateway.config import PlatformConfig from gateway.platforms.base import SendResult diff --git a/tests/gateway/test_weixin.py b/tests/gateway/test_weixin.py index 64258f7a29a..ac535865df8 100644 --- a/tests/gateway/test_weixin.py +++ b/tests/gateway/test_weixin.py @@ -4,7 +4,6 @@ import asyncio import base64 import json import os -from pathlib import Path from unittest.mock import AsyncMock, Mock, patch import pytest diff --git a/tests/gateway/test_whatsapp_formatting.py b/tests/gateway/test_whatsapp_formatting.py index 81b1a57c0c9..04b3174cdc2 100644 --- a/tests/gateway/test_whatsapp_formatting.py +++ b/tests/gateway/test_whatsapp_formatting.py @@ -7,11 +7,11 @@ Covers: """ import asyncio -from unittest.mock import AsyncMock, MagicMock, patch +from unittest.mock import AsyncMock, MagicMock import pytest -from gateway.config import Platform, PlatformConfig +from gateway.config import Platform # --------------------------------------------------------------------------- diff --git a/tests/gateway/test_whatsapp_group_gating.py b/tests/gateway/test_whatsapp_group_gating.py index 206c75830b7..75560633839 100644 --- a/tests/gateway/test_whatsapp_group_gating.py +++ b/tests/gateway/test_whatsapp_group_gating.py @@ -306,7 +306,6 @@ def test_status_broadcast_chats_are_always_dropped(): (a contact's WhatsApp Story update). These pseudo-chats aren't real conversations and the adapter must drop them regardless of dm_policy. """ - from gateway.platforms.whatsapp import WhatsAppAdapter # Even on the most permissive config — open DMs, no allowlist — Stories # and Channel posts must not reach the agent. diff --git a/tests/gateway/test_whatsapp_reply_prefix.py b/tests/gateway/test_whatsapp_reply_prefix.py index bf7a45c3dac..61f37332665 100644 --- a/tests/gateway/test_whatsapp_reply_prefix.py +++ b/tests/gateway/test_whatsapp_reply_prefix.py @@ -7,12 +7,10 @@ Covers: - Config version covers all ENV_VARS_BY_VERSION keys (regression guard) """ -from pathlib import Path -from unittest.mock import MagicMock, patch +from unittest.mock import patch -import pytest -from gateway.config import GatewayConfig, Platform, PlatformConfig +from gateway.config import Platform, PlatformConfig # --------------------------------------------------------------------------- diff --git a/tests/gateway/test_ws_auth_retry.py b/tests/gateway/test_ws_auth_retry.py index e413a30f938..ada5799538b 100644 --- a/tests/gateway/test_ws_auth_retry.py +++ b/tests/gateway/test_ws_auth_retry.py @@ -9,7 +9,6 @@ of stopping. These tests verify that auth errors now stop the reconnect. import asyncio from unittest.mock import AsyncMock, MagicMock, patch -import pytest # --------------------------------------------------------------------------- diff --git a/tests/hermes_cli/test_anthropic_model_flow_stale_oauth.py b/tests/hermes_cli/test_anthropic_model_flow_stale_oauth.py index e5526a34789..b6582776467 100644 --- a/tests/hermes_cli/test_anthropic_model_flow_stale_oauth.py +++ b/tests/hermes_cli/test_anthropic_model_flow_stale_oauth.py @@ -6,11 +6,8 @@ Claude Code credentials are available. The fast-path silently proceeds to model selection with a broken token instead of offering re-auth. """ -import json -import pytest -from unittest.mock import patch, MagicMock -from hermes_cli.config import load_env, save_env_value +from hermes_cli.config import save_env_value class TestStaleOAuthTokenDetection: diff --git a/tests/hermes_cli/test_api_key_providers.py b/tests/hermes_cli/test_api_key_providers.py index 902ff7a50f6..af576ed2995 100644 --- a/tests/hermes_cli/test_api_key_providers.py +++ b/tests/hermes_cli/test_api_key_providers.py @@ -6,7 +6,6 @@ import pytest from hermes_cli.auth import ( PROVIDER_REGISTRY, - ProviderConfig, resolve_provider, get_api_key_provider_status, resolve_api_key_provider_credentials, diff --git a/tests/hermes_cli/test_apply_profile_override.py b/tests/hermes_cli/test_apply_profile_override.py index c17c10c439f..6396faabd27 100644 --- a/tests/hermes_cli/test_apply_profile_override.py +++ b/tests/hermes_cli/test_apply_profile_override.py @@ -15,7 +15,6 @@ import os import sys from pathlib import Path -import pytest def _run_apply_profile_override( diff --git a/tests/hermes_cli/test_argparse_flag_propagation.py b/tests/hermes_cli/test_argparse_flag_propagation.py index c3d8e80db32..87db493850c 100644 --- a/tests/hermes_cli/test_argparse_flag_propagation.py +++ b/tests/hermes_cli/test_argparse_flag_propagation.py @@ -14,7 +14,6 @@ so the subparser only sets the attribute when the user explicitly provides it. import argparse import os import sys -from unittest.mock import patch import pytest diff --git a/tests/hermes_cli/test_atomic_json_write.py b/tests/hermes_cli/test_atomic_json_write.py index 08bed89ff36..6c3e94f6bb8 100644 --- a/tests/hermes_cli/test_atomic_json_write.py +++ b/tests/hermes_cli/test_atomic_json_write.py @@ -1,7 +1,6 @@ """Tests for utils.atomic_json_write — crash-safe JSON file writes.""" import json -import os from pathlib import Path from unittest.mock import patch diff --git a/tests/hermes_cli/test_atomic_yaml_write.py b/tests/hermes_cli/test_atomic_yaml_write.py index 6a9e4f00d5e..c76649fce66 100644 --- a/tests/hermes_cli/test_atomic_yaml_write.py +++ b/tests/hermes_cli/test_atomic_yaml_write.py @@ -1,6 +1,5 @@ """Tests for utils.atomic_yaml_write — crash-safe YAML file writes.""" -from pathlib import Path from unittest.mock import patch import pytest diff --git a/tests/hermes_cli/test_auth_codex_provider.py b/tests/hermes_cli/test_auth_codex_provider.py index 0d935eab39f..52a8a4a2c45 100644 --- a/tests/hermes_cli/test_auth_codex_provider.py +++ b/tests/hermes_cli/test_auth_codex_provider.py @@ -7,7 +7,6 @@ from pathlib import Path from types import SimpleNamespace import pytest -import yaml from hermes_cli.auth import ( AuthError, @@ -17,8 +16,6 @@ from hermes_cli.auth import ( _save_codex_tokens, _import_codex_cli_tokens, _login_openai_codex, - get_codex_auth_status, - get_provider_auth_state, refresh_codex_oauth_pure, resolve_codex_runtime_credentials, resolve_provider, diff --git a/tests/hermes_cli/test_auth_loopback_ssh_hint.py b/tests/hermes_cli/test_auth_loopback_ssh_hint.py index 87dcd526467..4525e89fcfc 100644 --- a/tests/hermes_cli/test_auth_loopback_ssh_hint.py +++ b/tests/hermes_cli/test_auth_loopback_ssh_hint.py @@ -11,7 +11,6 @@ import io import contextlib import socket -import pytest from hermes_cli import auth as auth_mod diff --git a/tests/hermes_cli/test_auth_provider_gate.py b/tests/hermes_cli/test_auth_provider_gate.py index f65ae71b856..561009d096c 100644 --- a/tests/hermes_cli/test_auth_provider_gate.py +++ b/tests/hermes_cli/test_auth_provider_gate.py @@ -1,7 +1,6 @@ """Tests for is_provider_explicitly_configured().""" import json -import os import pytest diff --git a/tests/hermes_cli/test_auth_qwen_provider.py b/tests/hermes_cli/test_auth_qwen_provider.py index a2f58df6b0b..6dd1ed91dda 100644 --- a/tests/hermes_cli/test_auth_qwen_provider.py +++ b/tests/hermes_cli/test_auth_qwen_provider.py @@ -6,7 +6,6 @@ resolve_qwen_runtime_credentials, get_qwen_auth_status. """ import json -import os import stat import time from pathlib import Path diff --git a/tests/hermes_cli/test_azure_foundry_entra.py b/tests/hermes_cli/test_azure_foundry_entra.py index 6cc2ff0ec97..f35312f0781 100644 --- a/tests/hermes_cli/test_azure_foundry_entra.py +++ b/tests/hermes_cli/test_azure_foundry_entra.py @@ -24,7 +24,6 @@ from __future__ import annotations import sys from types import SimpleNamespace from typing import cast -from unittest.mock import MagicMock, patch import pytest diff --git a/tests/hermes_cli/test_backup.py b/tests/hermes_cli/test_backup.py index 097b0b20957..a8657d77094 100644 --- a/tests/hermes_cli/test_backup.py +++ b/tests/hermes_cli/test_backup.py @@ -1029,7 +1029,6 @@ class TestProfileRestoration: args = Namespace(zipfile=str(zip_path), force=True) # Simulate profiles module not being available - import hermes_cli.backup as backup_mod original_import = __builtins__.__import__ if hasattr(__builtins__, '__import__') else __import__ def fake_import(name, *a, **kw): diff --git a/tests/hermes_cli/test_banner_skills.py b/tests/hermes_cli/test_banner_skills.py index 1006fcc8671..82518caa969 100644 --- a/tests/hermes_cli/test_banner_skills.py +++ b/tests/hermes_cli/test_banner_skills.py @@ -2,7 +2,6 @@ from unittest.mock import patch -import pytest _MOCK_SKILLS = [ diff --git a/tests/hermes_cli/test_bedrock_model_picker.py b/tests/hermes_cli/test_bedrock_model_picker.py index 70335be2186..0020341d491 100644 --- a/tests/hermes_cli/test_bedrock_model_picker.py +++ b/tests/hermes_cli/test_bedrock_model_picker.py @@ -16,12 +16,10 @@ Covers the three paths changed by fix/bedrock-provider-model-ids-live-discovery: All Bedrock API calls are mocked — no real AWS credentials needed. """ -import os from contextlib import contextmanager from types import ModuleType from unittest.mock import MagicMock, patch -import pytest # --------------------------------------------------------------------------- @@ -95,7 +93,7 @@ class TestProviderModelIdsBedrock: def test_falls_back_to_static_list_when_discovery_empty(self, monkeypatch): """When discover_bedrock_models() returns [], fall back to curated static list.""" - from hermes_cli.models import _PROVIDER_MODELS, provider_model_ids + from hermes_cli.models import provider_model_ids with patch("agent.bedrock_adapter.discover_bedrock_models", return_value=[]), \ patch("agent.bedrock_adapter.resolve_bedrock_region", return_value="eu-central-1"): diff --git a/tests/hermes_cli/test_bundles.py b/tests/hermes_cli/test_bundles.py index b089530ca98..8cd3a66a7aa 100644 --- a/tests/hermes_cli/test_bundles.py +++ b/tests/hermes_cli/test_bundles.py @@ -1,8 +1,6 @@ """Tests for hermes_cli/bundles.py — the `hermes bundles` CLI subcommand.""" import argparse -import sys -from pathlib import Path import pytest diff --git a/tests/hermes_cli/test_clear_stale_base_url.py b/tests/hermes_cli/test_clear_stale_base_url.py index 09f721bb7f1..b174cd32bfc 100644 --- a/tests/hermes_cli/test_clear_stale_base_url.py +++ b/tests/hermes_cli/test_clear_stale_base_url.py @@ -2,7 +2,6 @@ from __future__ import annotations -from unittest.mock import patch from hermes_cli.config import load_config, save_config, save_env_value, get_env_value diff --git a/tests/hermes_cli/test_coalesce_session_args.py b/tests/hermes_cli/test_coalesce_session_args.py index 32866dd5ee1..9971bb51bb6 100644 --- a/tests/hermes_cli/test_coalesce_session_args.py +++ b/tests/hermes_cli/test_coalesce_session_args.py @@ -1,6 +1,5 @@ """Tests for _coalesce_session_name_args — multi-word session name merging.""" -import pytest from hermes_cli.main import _coalesce_session_name_args diff --git a/tests/hermes_cli/test_codex_cli_model_picker.py b/tests/hermes_cli/test_codex_cli_model_picker.py index 4edbef2dea0..3968437a856 100644 --- a/tests/hermes_cli/test_codex_cli_model_picker.py +++ b/tests/hermes_cli/test_codex_cli_model_picker.py @@ -13,11 +13,8 @@ existing Codex CLI tokens via `hermes auth openai-codex`. The old import base64 import json -import os -import sys import time from pathlib import Path -from unittest.mock import patch import pytest diff --git a/tests/hermes_cli/test_codex_runtime_plugin_migration.py b/tests/hermes_cli/test_codex_runtime_plugin_migration.py index ebdc9f9ae6b..fc6df86c852 100644 --- a/tests/hermes_cli/test_codex_runtime_plugin_migration.py +++ b/tests/hermes_cli/test_codex_runtime_plugin_migration.py @@ -2,14 +2,12 @@ from __future__ import annotations -from pathlib import Path import pytest from hermes_cli.codex_runtime_plugin_migration import ( MIGRATION_MARKER, MIGRATION_END_MARKER, - MigrationReport, _build_hermes_tools_mcp_entry, _format_toml_value, _looks_like_test_tempdir, diff --git a/tests/hermes_cli/test_commands.py b/tests/hermes_cli/test_commands.py index 7324adbe430..b6e11e4c517 100644 --- a/tests/hermes_cli/test_commands.py +++ b/tests/hermes_cli/test_commands.py @@ -1003,7 +1003,7 @@ class TestTelegramMenuCommands: def test_excludes_telegram_disabled_skills(self, tmp_path, monkeypatch): """Skills disabled for telegram should not appear in the menu.""" - from unittest.mock import patch, MagicMock + from unittest.mock import patch # Set up a config with a telegram-specific disabled list config_file = tmp_path / "config.yaml" diff --git a/tests/hermes_cli/test_config.py b/tests/hermes_cli/test_config.py index d86017f2211..eb4827a4174 100644 --- a/tests/hermes_cli/test_config.py +++ b/tests/hermes_cli/test_config.py @@ -2,7 +2,7 @@ import os from pathlib import Path -from unittest.mock import patch, MagicMock +from unittest.mock import patch import pytest import yaml diff --git a/tests/hermes_cli/test_config_env_expansion.py b/tests/hermes_cli/test_config_env_expansion.py index 4de3480f734..435a4766878 100644 --- a/tests/hermes_cli/test_config_env_expansion.py +++ b/tests/hermes_cli/test_config_env_expansion.py @@ -1,9 +1,7 @@ """Tests for ${ENV_VAR} substitution in config.yaml values.""" -import os import pytest from hermes_cli.config import _expand_env_vars, load_config -from unittest.mock import patch as mock_patch class TestExpandEnvVars: diff --git a/tests/hermes_cli/test_config_validation.py b/tests/hermes_cli/test_config_validation.py index 7209e638f9a..f4423f5d7d1 100644 --- a/tests/hermes_cli/test_config_validation.py +++ b/tests/hermes_cli/test_config_validation.py @@ -1,6 +1,5 @@ """Tests for config.yaml structure validation (validate_config_structure).""" -import pytest from hermes_cli.config import validate_config_structure, ConfigIssue diff --git a/tests/hermes_cli/test_copilot_auth.py b/tests/hermes_cli/test_copilot_auth.py index 5c8fccf936a..3d0b0bdeb72 100644 --- a/tests/hermes_cli/test_copilot_auth.py +++ b/tests/hermes_cli/test_copilot_auth.py @@ -1,8 +1,7 @@ """Tests for hermes_cli.copilot_auth — Copilot token validation and resolution.""" -import os import pytest -from unittest.mock import patch, MagicMock +from unittest.mock import patch class TestTokenValidation: diff --git a/tests/hermes_cli/test_curator_archive_prune.py b/tests/hermes_cli/test_curator_archive_prune.py index 1ab28fb1778..ef8b914a8bf 100644 --- a/tests/hermes_cli/test_curator_archive_prune.py +++ b/tests/hermes_cli/test_curator_archive_prune.py @@ -12,12 +12,8 @@ Covers: from __future__ import annotations -import io -from contextlib import redirect_stdout, redirect_stderr from types import SimpleNamespace -from unittest.mock import patch -import pytest def _ns(**kwargs): diff --git a/tests/hermes_cli/test_curses_color_compat.py b/tests/hermes_cli/test_curses_color_compat.py index c7509cc965f..2416ded1230 100644 --- a/tests/hermes_cli/test_curses_color_compat.py +++ b/tests/hermes_cli/test_curses_color_compat.py @@ -12,9 +12,8 @@ clamps with ``min(8, curses.COLORS - 1)``. import curses import re from pathlib import Path -from unittest.mock import patch, MagicMock, call +from unittest.mock import patch, MagicMock -import pytest # Path to the source files under test diff --git a/tests/hermes_cli/test_custom_provider_model_switch.py b/tests/hermes_cli/test_custom_provider_model_switch.py index 1c14b848439..0f3a76a1ab9 100644 --- a/tests/hermes_cli/test_custom_provider_model_switch.py +++ b/tests/hermes_cli/test_custom_provider_model_switch.py @@ -6,8 +6,7 @@ immediately when provider_info had a saved ``model`` field, making it impossible to switch models on multi-model endpoints. """ -import os -from unittest.mock import patch, MagicMock, call +from unittest.mock import patch import pytest diff --git a/tests/hermes_cli/test_dashboard_auth_cookies.py b/tests/hermes_cli/test_dashboard_auth_cookies.py index 24d6f4b9168..7109b7b7099 100644 --- a/tests/hermes_cli/test_dashboard_auth_cookies.py +++ b/tests/hermes_cli/test_dashboard_auth_cookies.py @@ -1,7 +1,6 @@ """Tests for the dashboard-auth cookie helpers.""" from __future__ import annotations -import pytest from fastapi import FastAPI from fastapi.responses import Response from fastapi.testclient import TestClient diff --git a/tests/hermes_cli/test_dashboard_auth_prefix.py b/tests/hermes_cli/test_dashboard_auth_prefix.py index c7afce226b8..74366c9c009 100644 --- a/tests/hermes_cli/test_dashboard_auth_prefix.py +++ b/tests/hermes_cli/test_dashboard_auth_prefix.py @@ -177,7 +177,7 @@ class TestOAuthRedirectUriRespectsPrefix: # The stub IDP's redirect_url echoes the redirect_uri back. The # real IDP would consume it and later use it to redirect the # user, so the byte-exact value MUST include the prefix. - from urllib.parse import urlparse, parse_qs, unquote + from urllib.parse import urlparse # Stub returns ``{redirect_uri}?code=stub_code&state=...`` — so # we read up to the first ``?``. redirect_uri = location.split("?", 1)[0] diff --git a/tests/hermes_cli/test_dashboard_auth_ws_auth.py b/tests/hermes_cli/test_dashboard_auth_ws_auth.py index 44087e53b4d..0ebed6d9519 100644 --- a/tests/hermes_cli/test_dashboard_auth_ws_auth.py +++ b/tests/hermes_cli/test_dashboard_auth_ws_auth.py @@ -14,7 +14,6 @@ pre-existing regression unrelated to dashboard-auth. from __future__ import annotations from types import SimpleNamespace -from unittest.mock import patch import pytest @@ -29,7 +28,6 @@ from fastapi.testclient import TestClient from hermes_cli import web_server from hermes_cli.dashboard_auth import clear_providers, register_provider from hermes_cli.dashboard_auth.ws_tickets import ( - TicketInvalid, _reset_for_tests, consume_ticket, mint_ticket, diff --git a/tests/hermes_cli/test_dashboard_lifecycle_flags.py b/tests/hermes_cli/test_dashboard_lifecycle_flags.py index c0c505fc33a..0e6f161572f 100644 --- a/tests/hermes_cli/test_dashboard_lifecycle_flags.py +++ b/tests/hermes_cli/test_dashboard_lifecycle_flags.py @@ -15,7 +15,7 @@ from unittest.mock import patch, MagicMock import pytest -from hermes_cli.main import cmd_dashboard, _report_dashboard_status +from hermes_cli.main import cmd_dashboard def _ns(**kw): diff --git a/tests/hermes_cli/test_debug.py b/tests/hermes_cli/test_debug.py index aad1c8e92a5..b3ce60de2f4 100644 --- a/tests/hermes_cli/test_debug.py +++ b/tests/hermes_cli/test_debug.py @@ -1,10 +1,8 @@ """Tests for ``hermes debug`` CLI command and debug utilities.""" import os -import sys import urllib.error -from pathlib import Path -from unittest.mock import MagicMock, patch, call +from unittest.mock import MagicMock, patch import pytest @@ -337,7 +335,6 @@ class TestCaptureLogSnapshotRedaction: redaction feature ships silently broken for users who opted out of runtime redaction (e.g. developers working on the redactor itself). """ - import os # Force the runtime flag off so we're exercising the force=True path, # not the default-on path. diff --git a/tests/hermes_cli/test_dep_ensure.py b/tests/hermes_cli/test_dep_ensure.py index 77fee5b7ec5..a19a6de63f2 100644 --- a/tests/hermes_cli/test_dep_ensure.py +++ b/tests/hermes_cli/test_dep_ensure.py @@ -1,4 +1,3 @@ -from pathlib import Path from unittest.mock import patch diff --git a/tests/hermes_cli/test_deprecated_cwd_warning.py b/tests/hermes_cli/test_deprecated_cwd_warning.py index 4b438e7ebf2..2d449d20cc5 100644 --- a/tests/hermes_cli/test_deprecated_cwd_warning.py +++ b/tests/hermes_cli/test_deprecated_cwd_warning.py @@ -1,7 +1,5 @@ """Tests for warn_deprecated_cwd_env_vars() migration warning.""" -import os -import pytest class TestDeprecatedCwdWarning: diff --git a/tests/hermes_cli/test_doctor.py b/tests/hermes_cli/test_doctor.py index 23895477ee0..e1edc95af1a 100644 --- a/tests/hermes_cli/test_doctor.py +++ b/tests/hermes_cli/test_doctor.py @@ -792,7 +792,7 @@ class TestGitHubTokenCheck: monkeypatch.setenv("HERMES_HOME", str(home)) monkeypatch.setenv("PATH", "/nonexistent") # gh not found - from hermes_cli.doctor import run_doctor, _DHH + from hermes_cli.doctor import run_doctor import io, contextlib buf = io.StringIO() diff --git a/tests/hermes_cli/test_doctor_command_install.py b/tests/hermes_cli/test_doctor_command_install.py index 8b046b9c2c1..f394c29e92e 100644 --- a/tests/hermes_cli/test_doctor_command_install.py +++ b/tests/hermes_cli/test_doctor_command_install.py @@ -1,6 +1,5 @@ """Tests for the Command Installation check in hermes doctor.""" -import os import sys import types from argparse import Namespace diff --git a/tests/hermes_cli/test_env_loader.py b/tests/hermes_cli/test_env_loader.py index 2523754a84b..f719fae01ce 100644 --- a/tests/hermes_cli/test_env_loader.py +++ b/tests/hermes_cli/test_env_loader.py @@ -1,7 +1,6 @@ import importlib import os import sys -from pathlib import Path from hermes_cli.env_loader import load_hermes_dotenv diff --git a/tests/hermes_cli/test_fallback_cmd.py b/tests/hermes_cli/test_fallback_cmd.py index 2eed7d62f97..bc7817cf9c9 100644 --- a/tests/hermes_cli/test_fallback_cmd.py +++ b/tests/hermes_cli/test_fallback_cmd.py @@ -1,7 +1,6 @@ """Tests for `hermes fallback` — chain reading, add/remove/clear, legacy migration.""" from __future__ import annotations -import io import types from pathlib import Path from unittest.mock import patch diff --git a/tests/hermes_cli/test_gateway.py b/tests/hermes_cli/test_gateway.py index d78dcc131af..4d78b396be1 100644 --- a/tests/hermes_cli/test_gateway.py +++ b/tests/hermes_cli/test_gateway.py @@ -2,7 +2,6 @@ import sys from types import ModuleType, SimpleNamespace -from unittest.mock import patch, call import pytest diff --git a/tests/hermes_cli/test_gateway_platform_gating.py b/tests/hermes_cli/test_gateway_platform_gating.py index c16875687ce..16a51d419b7 100644 --- a/tests/hermes_cli/test_gateway_platform_gating.py +++ b/tests/hermes_cli/test_gateway_platform_gating.py @@ -12,7 +12,6 @@ Currently: Windows path that works. """ -import sys class TestMatrixHiddenOnWindows: diff --git a/tests/hermes_cli/test_gateway_s6_dispatch.py b/tests/hermes_cli/test_gateway_s6_dispatch.py index d7146b2a397..c730da7219c 100644 --- a/tests/hermes_cli/test_gateway_s6_dispatch.py +++ b/tests/hermes_cli/test_gateway_s6_dispatch.py @@ -7,7 +7,6 @@ host systemd/launchd/windows code path. """ from __future__ import annotations -from typing import Any import pytest diff --git a/tests/hermes_cli/test_gateway_service.py b/tests/hermes_cli/test_gateway_service.py index b1fcadbf4f0..a8f65123d8b 100644 --- a/tests/hermes_cli/test_gateway_service.py +++ b/tests/hermes_cli/test_gateway_service.py @@ -1321,7 +1321,6 @@ class TestSystemServiceIdentityRootHandling: def test_auto_detected_root_is_rejected(self, monkeypatch): """When root is auto-detected (not explicitly requested), raise.""" - import grp monkeypatch.delenv("SUDO_USER", raising=False) monkeypatch.setenv("USER", "root") @@ -1343,7 +1342,6 @@ class TestSystemServiceIdentityRootHandling: def test_non_root_user_passes_through(self, monkeypatch): """Normal non-root user works as before.""" - import grp monkeypatch.delenv("SUDO_USER", raising=False) monkeypatch.setenv("USER", "nobody") diff --git a/tests/hermes_cli/test_gateway_service_paths.py b/tests/hermes_cli/test_gateway_service_paths.py index 71abc4aef24..86bca738274 100644 --- a/tests/hermes_cli/test_gateway_service_paths.py +++ b/tests/hermes_cli/test_gateway_service_paths.py @@ -1,4 +1,3 @@ -from pathlib import Path from unittest.mock import patch diff --git a/tests/hermes_cli/test_gateway_wsl.py b/tests/hermes_cli/test_gateway_wsl.py index 8fbbe24245d..d12391a9fb0 100644 --- a/tests/hermes_cli/test_gateway_wsl.py +++ b/tests/hermes_cli/test_gateway_wsl.py @@ -1,8 +1,6 @@ """Tests for WSL detection and WSL-aware gateway behavior.""" -import io import subprocess -import sys from types import SimpleNamespace from unittest.mock import patch, MagicMock, mock_open diff --git a/tests/hermes_cli/test_gemini_provider.py b/tests/hermes_cli/test_gemini_provider.py index 1daeb281f0e..61d7bc48ebb 100644 --- a/tests/hermes_cli/test_gemini_provider.py +++ b/tests/hermes_cli/test_gemini_provider.py @@ -1,6 +1,5 @@ """Tests for Google AI Studio (Gemini) provider integration.""" -import os import pytest from unittest.mock import patch, MagicMock diff --git a/tests/hermes_cli/test_goals.py b/tests/hermes_cli/test_goals.py index 9d8c3f48fe1..0dae684b629 100644 --- a/tests/hermes_cli/test_goals.py +++ b/tests/hermes_cli/test_goals.py @@ -525,7 +525,6 @@ class TestGoalStateSubgoalsBackcompat: def test_old_state_meta_row_loads_without_subgoals(self): """A goal serialized BEFORE the subgoals field existed must round-trip with an empty list, not crash.""" - import json from hermes_cli.goals import GoalState legacy = json.dumps({ @@ -647,7 +646,7 @@ class TestJudgeGoalWithSubgoals: We don't actually call the model — we patch the aux client to capture the prompt that would be sent. """ - from unittest.mock import patch, MagicMock + from unittest.mock import patch from hermes_cli import goals captured = {} diff --git a/tests/hermes_cli/test_hooks_cli.py b/tests/hermes_cli/test_hooks_cli.py index 6d4609c523c..3713df10ad6 100644 --- a/tests/hermes_cli/test_hooks_cli.py +++ b/tests/hermes_cli/test_hooks_cli.py @@ -4,7 +4,6 @@ from __future__ import annotations import io import json -import sys from contextlib import redirect_stdout from pathlib import Path from types import SimpleNamespace diff --git a/tests/hermes_cli/test_inventory.py b/tests/hermes_cli/test_inventory.py index baf48ecbb04..1b24ba6bdd6 100644 --- a/tests/hermes_cli/test_inventory.py +++ b/tests/hermes_cli/test_inventory.py @@ -21,7 +21,6 @@ from __future__ import annotations from unittest.mock import patch -import pytest from hermes_cli.inventory import ( ConfigContext, diff --git a/tests/hermes_cli/test_kanban_core_functionality.py b/tests/hermes_cli/test_kanban_core_functionality.py index 05fb31c4d5f..c28671dde51 100644 --- a/tests/hermes_cli/test_kanban_core_functionality.py +++ b/tests/hermes_cli/test_kanban_core_functionality.py @@ -18,7 +18,6 @@ import threading import time from pathlib import Path from types import SimpleNamespace -from typing import Optional import pytest diff --git a/tests/hermes_cli/test_kanban_db.py b/tests/hermes_cli/test_kanban_db.py index 69049b20938..020ad4fb425 100644 --- a/tests/hermes_cli/test_kanban_db.py +++ b/tests/hermes_cli/test_kanban_db.py @@ -2566,7 +2566,6 @@ def test_resolve_hermes_argv_module_actually_runs(): Run it as a real subprocess to catch that regression. """ import subprocess - import sys import hermes_cli.kanban_db as kb import shutil import unittest.mock as mock @@ -3145,7 +3144,6 @@ def test_detect_stale_skips_recently_started_task(kanban_home, monkeypatch): def test_detect_stale_skips_when_timeout_zero(kanban_home, monkeypatch): """stale_timeout_seconds=0 disables stale detection entirely.""" - import hermes_cli.kanban_db as _kb with kb.connect() as conn: t = kb.create_task(conn, title="disabled", assignee="worker") @@ -3628,7 +3626,7 @@ def test_write_txn_preserves_original_exception_when_rollback_fails(kanban_home) ) def test_write_txn_healthy_commit_no_exception(tmp_path): """Normal commit does not trigger the torn-extend check.""" - from hermes_cli.kanban_db import connect, write_txn, create_task + from hermes_cli.kanban_db import connect, write_txn db = tmp_path / "test.db" conn = connect(db_path=db) # Should not raise @@ -3645,7 +3643,6 @@ def test_write_txn_healthy_commit_no_exception(tmp_path): def test_write_txn_raises_on_truncated_file(tmp_path): """A mocked smaller file size triggers the torn-extend check.""" from hermes_cli.kanban_db import connect, write_txn - import hermes_cli.kanban_db as kanban_db_module db = tmp_path / "test.db" conn = connect(db_path=db) # Get actual page size so we can fake a smaller file @@ -3705,7 +3702,7 @@ def test_connect_sets_wal_autocheckpoint_100(tmp_path): def test_write_txn_check_reads_correct_header_fields(tmp_path): """Synthetic DB file with mismatched header page_count triggers the check.""" import struct - from hermes_cli.kanban_db import connect, write_txn, _check_file_length_invariant + from hermes_cli.kanban_db import connect, _check_file_length_invariant db = tmp_path / "synthetic.db" conn = connect(db_path=db) page_size = conn.execute("PRAGMA page_size").fetchone()[0] diff --git a/tests/hermes_cli/test_kanban_decompose.py b/tests/hermes_cli/test_kanban_decompose.py index 62937abba28..5ba17e58cae 100644 --- a/tests/hermes_cli/test_kanban_decompose.py +++ b/tests/hermes_cli/test_kanban_decompose.py @@ -7,14 +7,12 @@ and the assignee-fallback logic. from __future__ import annotations -import argparse import json as jsonlib from pathlib import Path from unittest.mock import MagicMock, patch import pytest -from hermes_cli import kanban as kanban_cli from hermes_cli import kanban_db as kb from hermes_cli import kanban_decompose as decomp diff --git a/tests/hermes_cli/test_kanban_notify.py b/tests/hermes_cli/test_kanban_notify.py index 44a0bd90a03..f8109416cb5 100644 --- a/tests/hermes_cli/test_kanban_notify.py +++ b/tests/hermes_cli/test_kanban_notify.py @@ -298,7 +298,6 @@ def test_dispatcher_tick_does_not_call_init_db(kanban_home, monkeypatch): """ import hermes_cli.kanban_db as kb from gateway.run import GatewayRunner - from unittest.mock import patch runner = object.__new__(GatewayRunner) diff --git a/tests/hermes_cli/test_kanban_swarm.py b/tests/hermes_cli/test_kanban_swarm.py index 358e41d4611..eeb6f917a3c 100644 --- a/tests/hermes_cli/test_kanban_swarm.py +++ b/tests/hermes_cli/test_kanban_swarm.py @@ -1,4 +1,3 @@ -import json from hermes_cli import kanban_db as kb from hermes_cli.kanban_swarm import ( diff --git a/tests/hermes_cli/test_logs.py b/tests/hermes_cli/test_logs.py index 0827143fc67..203a37af5a5 100644 --- a/tests/hermes_cli/test_logs.py +++ b/tests/hermes_cli/test_logs.py @@ -1,10 +1,7 @@ """Tests for hermes_cli.logs — log viewing and filtering.""" -import os from datetime import datetime, timedelta -from pathlib import Path -import pytest from hermes_cli.logs import ( LOG_FILES, diff --git a/tests/hermes_cli/test_mcp_catalog.py b/tests/hermes_cli/test_mcp_catalog.py index 13dcf50653b..bb15c48ce8c 100644 --- a/tests/hermes_cli/test_mcp_catalog.py +++ b/tests/hermes_cli/test_mcp_catalog.py @@ -7,7 +7,6 @@ launch an MCP is mocked. from __future__ import annotations -import os from pathlib import Path from unittest.mock import patch @@ -207,7 +206,7 @@ class TestManifestParsing: class TestInstall: def test_install_simple_stdio_writes_config(self, catalog_dir): _write_manifest(catalog_dir, "demo", _basic_manifest()) - from hermes_cli.mcp_catalog import install_entry, get_entry + from hermes_cli.mcp_catalog import install_entry from hermes_cli.config import load_config install_entry(_entry("demo"), enable=True) @@ -240,7 +239,7 @@ class TestInstall: fake_clone.mkdir() from hermes_cli import mcp_catalog - from hermes_cli.mcp_catalog import install_entry, get_entry + from hermes_cli.mcp_catalog import install_entry from hermes_cli.config import load_config with patch.object(mcp_catalog, "_do_git_install", return_value=fake_clone): @@ -263,7 +262,7 @@ class TestInstall: monkeypatch.setattr(mcp_catalog, "_prompt_input", lambda *a, **kw: "secret-val") - from hermes_cli.mcp_catalog import install_entry, get_entry + from hermes_cli.mcp_catalog import install_entry from hermes_cli.config import get_env_value, load_config install_entry(_entry("demo"), enable=True) @@ -278,7 +277,7 @@ class TestInstall: ) _write_manifest(catalog_dir, "demo", body) - from hermes_cli.mcp_catalog import install_entry, get_entry + from hermes_cli.mcp_catalog import install_entry from hermes_cli.config import load_config install_entry(_entry("demo"), enable=True) @@ -297,7 +296,7 @@ class TestInstall: _write_manifest(catalog_dir, "demo", body) from hermes_cli import mcp_catalog - from hermes_cli.mcp_catalog import install_entry, get_entry, CatalogError + from hermes_cli.mcp_catalog import install_entry, CatalogError # User hits enter — empty input, no default monkeypatch.setattr(mcp_catalog, "_prompt_input", lambda *a, **kw: "") @@ -314,7 +313,7 @@ class TestInstall: class TestUninstall: def test_uninstall_removes_server_block(self, catalog_dir): _write_manifest(catalog_dir, "demo", _basic_manifest()) - from hermes_cli.mcp_catalog import install_entry, get_entry, uninstall_entry + from hermes_cli.mcp_catalog import install_entry, uninstall_entry from hermes_cli.config import load_config install_entry(_entry("demo"), enable=True) diff --git a/tests/hermes_cli/test_mcp_config.py b/tests/hermes_cli/test_mcp_config.py index e136f1b3c0f..ac080afd028 100644 --- a/tests/hermes_cli/test_mcp_config.py +++ b/tests/hermes_cli/test_mcp_config.py @@ -6,12 +6,7 @@ any actual MCP servers or API keys. """ import argparse -import json -import os -import types from pathlib import Path -from typing import Any, Dict, List -from unittest.mock import MagicMock, patch, PropertyMock import pytest diff --git a/tests/hermes_cli/test_mcp_reload_confirm_gate.py b/tests/hermes_cli/test_mcp_reload_confirm_gate.py index 871f46fe7e1..a7d949e765b 100644 --- a/tests/hermes_cli/test_mcp_reload_confirm_gate.py +++ b/tests/hermes_cli/test_mcp_reload_confirm_gate.py @@ -10,7 +10,6 @@ run silently. from __future__ import annotations -from copy import deepcopy from hermes_cli.config import DEFAULT_CONFIG diff --git a/tests/hermes_cli/test_mcp_tools_config.py b/tests/hermes_cli/test_mcp_tools_config.py index ada221a3ddc..e3b73231ca9 100644 --- a/tests/hermes_cli/test_mcp_tools_config.py +++ b/tests/hermes_cli/test_mcp_tools_config.py @@ -1,7 +1,6 @@ """Tests for MCP tools interactive configuration in hermes_cli.tools_config.""" -from types import SimpleNamespace -from unittest.mock import MagicMock, patch +from unittest.mock import patch from hermes_cli.tools_config import _configure_mcp_tools_interactive diff --git a/tests/hermes_cli/test_memory_reset.py b/tests/hermes_cli/test_memory_reset.py index 48f1cfda6a7..34b7f53caa1 100644 --- a/tests/hermes_cli/test_memory_reset.py +++ b/tests/hermes_cli/test_memory_reset.py @@ -8,10 +8,7 @@ Covers: - Profile-scoped reset (uses HERMES_HOME) """ -import os import pytest -from argparse import Namespace -from pathlib import Path @pytest.fixture @@ -39,7 +36,7 @@ def _run_memory_reset(target="all", yes=False, monkeypatch=None, confirm_input=" Simulates what happens when `hermes memory reset` is run. """ - from hermes_constants import get_hermes_home, display_hermes_home + from hermes_constants import get_hermes_home mem_dir = get_hermes_home() / "memories" files_to_reset = [] diff --git a/tests/hermes_cli/test_model_normalize.py b/tests/hermes_cli/test_model_normalize.py index f2a4bf3d684..7e4a6d22e87 100644 --- a/tests/hermes_cli/test_model_normalize.py +++ b/tests/hermes_cli/test_model_normalize.py @@ -8,7 +8,6 @@ import pytest from hermes_cli.model_normalize import ( normalize_model_for_provider, _DOT_TO_HYPHEN_PROVIDERS, - _AGGREGATOR_PROVIDERS, _normalize_for_deepseek, detect_vendor, ) diff --git a/tests/hermes_cli/test_model_provider_persistence.py b/tests/hermes_cli/test_model_provider_persistence.py index 0b350ba9adb..aef758f099e 100644 --- a/tests/hermes_cli/test_model_provider_persistence.py +++ b/tests/hermes_cli/test_model_provider_persistence.py @@ -6,7 +6,6 @@ isinstance(model, dict)) to silently fail — leaving the provider unset and falling back to auto-detection. """ -import os from unittest.mock import patch, MagicMock import pytest @@ -194,7 +193,6 @@ class TestProviderPersistsAfterModelSave: # Patch fetch_api_models so the named custom flow returns one model; # patch simple_term_menu to force the input() fallback; patch input to # auto-select the first model from the fallback prompt. - from unittest.mock import MagicMock fake_menu_module = MagicMock() fake_menu_module.TerminalMenu.side_effect = OSError("no tty in test") with patch("hermes_cli.auth._save_model_choice"), \ diff --git a/tests/hermes_cli/test_models_dev_preferred_merge.py b/tests/hermes_cli/test_models_dev_preferred_merge.py index 0345643f368..c760f0da39f 100644 --- a/tests/hermes_cli/test_models_dev_preferred_merge.py +++ b/tests/hermes_cli/test_models_dev_preferred_merge.py @@ -17,10 +17,8 @@ Merging is what lets new models (e.g. ``mimo-v2.5-pro`` on opencode-go) appear in ``/model`` without a Hermes release. """ -import os from unittest.mock import patch -import pytest from hermes_cli.models import ( _MODELS_DEV_PREFERRED, diff --git a/tests/hermes_cli/test_non_ascii_credential.py b/tests/hermes_cli/test_non_ascii_credential.py index caac425c2b6..6f079442681 100644 --- a/tests/hermes_cli/test_non_ascii_credential.py +++ b/tests/hermes_cli/test_non_ascii_credential.py @@ -6,10 +6,7 @@ httpx tries to encode the Authorization header as ASCII. """ import os -import sys -import tempfile -import pytest from hermes_cli.config import _check_non_ascii_credential diff --git a/tests/hermes_cli/test_nous_inference_url_validation.py b/tests/hermes_cli/test_nous_inference_url_validation.py index 4e688a59a74..f4f899462b7 100644 --- a/tests/hermes_cli/test_nous_inference_url_validation.py +++ b/tests/hermes_cli/test_nous_inference_url_validation.py @@ -22,7 +22,6 @@ These tests verify: from __future__ import annotations import logging -import pytest from hermes_cli.auth import ( DEFAULT_NOUS_INFERENCE_URL, diff --git a/tests/hermes_cli/test_ollama_cloud_auth.py b/tests/hermes_cli/test_ollama_cloud_auth.py index 760832523cd..7e2dc5ff078 100644 --- a/tests/hermes_cli/test_ollama_cloud_auth.py +++ b/tests/hermes_cli/test_ollama_cloud_auth.py @@ -10,8 +10,6 @@ Covers: """ import os -import pytest -from unittest.mock import patch, MagicMock # --------------------------------------------------------------------------- diff --git a/tests/hermes_cli/test_ollama_cloud_provider.py b/tests/hermes_cli/test_ollama_cloud_provider.py index e40ba8ccc86..e62aa899ff8 100644 --- a/tests/hermes_cli/test_ollama_cloud_provider.py +++ b/tests/hermes_cli/test_ollama_cloud_provider.py @@ -1,6 +1,5 @@ """Tests for Ollama Cloud provider integration.""" -import os import pytest from unittest.mock import patch, MagicMock diff --git a/tests/hermes_cli/test_overlay_slug_resolution.py b/tests/hermes_cli/test_overlay_slug_resolution.py index c87c891f97e..2b03926250f 100644 --- a/tests/hermes_cli/test_overlay_slug_resolution.py +++ b/tests/hermes_cli/test_overlay_slug_resolution.py @@ -7,11 +7,9 @@ resolution in list_authenticated_providers() Section 2 must bridge this gap. Covers: #5223, #6492 """ -import json import os from unittest.mock import patch -import pytest from hermes_cli.model_switch import list_authenticated_providers diff --git a/tests/hermes_cli/test_pip_install_detection.py b/tests/hermes_cli/test_pip_install_detection.py index da3dd35e329..bfdc8be4ff2 100644 --- a/tests/hermes_cli/test_pip_install_detection.py +++ b/tests/hermes_cli/test_pip_install_detection.py @@ -1,4 +1,3 @@ -from pathlib import Path from unittest.mock import patch diff --git a/tests/hermes_cli/test_plugin_cli_registration.py b/tests/hermes_cli/test_plugin_cli_registration.py index af923b96a0d..0deddc8506b 100644 --- a/tests/hermes_cli/test_plugin_cli_registration.py +++ b/tests/hermes_cli/test_plugin_cli_registration.py @@ -8,13 +8,9 @@ Covers: - Honcho register_cli() builds correct argparse tree """ -import argparse -import os import sys -from pathlib import Path from unittest.mock import MagicMock -import pytest from hermes_cli.plugins import ( PluginContext, diff --git a/tests/hermes_cli/test_plugin_scanner_recursion.py b/tests/hermes_cli/test_plugin_scanner_recursion.py index b6e26416811..7a2513e074a 100644 --- a/tests/hermes_cli/test_plugin_scanner_recursion.py +++ b/tests/hermes_cli/test_plugin_scanner_recursion.py @@ -14,7 +14,7 @@ from typing import Any, Dict import pytest import yaml -from hermes_cli.plugins import PluginManager, PluginManifest +from hermes_cli.plugins import PluginManager # ── Helpers ──────────────────────────────────────────────────────────────── diff --git a/tests/hermes_cli/test_plugins.py b/tests/hermes_cli/test_plugins.py index 0c500297a2b..b78e8b2921d 100644 --- a/tests/hermes_cli/test_plugins.py +++ b/tests/hermes_cli/test_plugins.py @@ -1,7 +1,6 @@ """Tests for the Hermes plugin system (hermes_cli.plugins).""" import logging -import os import sys import types from pathlib import Path @@ -13,17 +12,13 @@ import yaml from hermes_cli.plugins import ( ENTRY_POINTS_GROUP, VALID_HOOKS, - LoadedPlugin, PluginContext, PluginManager, PluginManifest, - get_plugin_manager, get_plugin_command_handler, get_plugin_commands, get_pre_tool_call_block_message, resolve_plugin_command_result, - discover_plugins, - invoke_hook, ) @@ -1309,7 +1304,6 @@ class TestPluginCommandResultResolution: monkeypatch.setattr("hermes_cli.plugins.asyncio.get_running_loop", lambda: _Loop()) monkeypatch.setattr("hermes_cli.plugins._PLUGIN_COMMAND_AWAIT_TIMEOUT_SECS", 0.1) - import pytest with pytest.raises(TimeoutError): resolve_plugin_command_result(_slow_handler()) diff --git a/tests/hermes_cli/test_plugins_cmd.py b/tests/hermes_cli/test_plugins_cmd.py index c918246e4e7..5f8abcc8762 100644 --- a/tests/hermes_cli/test_plugins_cmd.py +++ b/tests/hermes_cli/test_plugins_cmd.py @@ -3,8 +3,6 @@ from __future__ import annotations import logging -import os -import types from pathlib import Path from unittest.mock import MagicMock, patch @@ -19,7 +17,6 @@ from hermes_cli.plugins_cmd import ( _resolve_git_executable, _resolve_git_url, _sanitize_plugin_name, - plugins_command, ) @@ -259,7 +256,6 @@ class TestCmdInstall: def test_install_requires_identifier(self): from hermes_cli.plugins_cmd import cmd_install - import argparse with pytest.raises(SystemExit): cmd_install("") @@ -544,7 +540,6 @@ class TestCopyExampleFiles: """Test example file copying.""" def test_copies_example_files(self, tmp_path): - from hermes_cli.plugins_cmd import _copy_example_files from unittest.mock import MagicMock console = MagicMock() @@ -560,7 +555,6 @@ class TestCopyExampleFiles: console.print.assert_called() def test_skips_existing_files(self, tmp_path): - from hermes_cli.plugins_cmd import _copy_example_files from unittest.mock import MagicMock console = MagicMock() @@ -577,7 +571,6 @@ class TestCopyExampleFiles: assert real_file.read_text() == "existing: true" def test_handles_copy_error_gracefully(self, tmp_path): - from hermes_cli.plugins_cmd import _copy_example_files from unittest.mock import MagicMock, patch console = MagicMock() diff --git a/tests/hermes_cli/test_profile_distribution.py b/tests/hermes_cli/test_profile_distribution.py index cf27df91b69..235316bd843 100644 --- a/tests/hermes_cli/test_profile_distribution.py +++ b/tests/hermes_cli/test_profile_distribution.py @@ -10,7 +10,6 @@ mocking git would just test the mock. from __future__ import annotations -import os from pathlib import Path import pytest diff --git a/tests/hermes_cli/test_profile_export_credentials.py b/tests/hermes_cli/test_profile_export_credentials.py index b26937e3512..f035f986f23 100644 --- a/tests/hermes_cli/test_profile_export_credentials.py +++ b/tests/hermes_cli/test_profile_export_credentials.py @@ -6,7 +6,6 @@ profiles; leaking credentials in the archive is a security issue. """ import tarfile -from pathlib import Path from hermes_cli.profiles import export_profile, _DEFAULT_EXPORT_EXCLUDE_ROOT diff --git a/tests/hermes_cli/test_profiles.py b/tests/hermes_cli/test_profiles.py index 4b521fa94da..0e3fcb1d76e 100644 --- a/tests/hermes_cli/test_profiles.py +++ b/tests/hermes_cli/test_profiles.py @@ -7,7 +7,6 @@ and shell completion generation. import json import io -import os import tarfile from pathlib import Path from unittest.mock import patch, MagicMock diff --git a/tests/hermes_cli/test_project_plugin_rce_bypass.py b/tests/hermes_cli/test_project_plugin_rce_bypass.py index 7dc5ee803e2..1e12b47eb9d 100644 --- a/tests/hermes_cli/test_project_plugin_rce_bypass.py +++ b/tests/hermes_cli/test_project_plugin_rce_bypass.py @@ -31,7 +31,6 @@ These tests pin each layer of the new defence: from __future__ import annotations import json -import os import sys from pathlib import Path from unittest.mock import patch diff --git a/tests/hermes_cli/test_provider_config_validation.py b/tests/hermes_cli/test_provider_config_validation.py index cbfffea7854..50cc283d90c 100644 --- a/tests/hermes_cli/test_provider_config_validation.py +++ b/tests/hermes_cli/test_provider_config_validation.py @@ -5,9 +5,7 @@ accepted as base_url, and unknown keys go unreported. """ import logging -from unittest.mock import patch -import pytest from hermes_cli.config import _normalize_custom_provider_entry diff --git a/tests/hermes_cli/test_proxy.py b/tests/hermes_cli/test_proxy.py index 878efb6469d..edc1425b58d 100644 --- a/tests/hermes_cli/test_proxy.py +++ b/tests/hermes_cli/test_proxy.py @@ -4,7 +4,6 @@ from __future__ import annotations import asyncio import json -import os import threading from pathlib import Path from typing import Any, Dict diff --git a/tests/hermes_cli/test_regression_16767.py b/tests/hermes_cli/test_regression_16767.py index 4aea5d64094..bbbae4df587 100644 --- a/tests/hermes_cli/test_regression_16767.py +++ b/tests/hermes_cli/test_regression_16767.py @@ -1,7 +1,4 @@ -import pytest import sys -from unittest.mock import patch -from pathlib import Path import hermes_cli.model_switch as ms from hermes_cli.model_switch import DirectAlias diff --git a/tests/hermes_cli/test_security_audit.py b/tests/hermes_cli/test_security_audit.py index fe6abe7221c..0a8d70c1d7b 100644 --- a/tests/hermes_cli/test_security_audit.py +++ b/tests/hermes_cli/test_security_audit.py @@ -10,7 +10,6 @@ import json from pathlib import Path from unittest.mock import patch -import pytest from hermes_cli import security_audit as sa diff --git a/tests/hermes_cli/test_send_cmd.py b/tests/hermes_cli/test_send_cmd.py index 802cff88c90..218227266b7 100644 --- a/tests/hermes_cli/test_send_cmd.py +++ b/tests/hermes_cli/test_send_cmd.py @@ -9,7 +9,6 @@ from __future__ import annotations import io import json -from pathlib import Path import pytest diff --git a/tests/hermes_cli/test_service_manager.py b/tests/hermes_cli/test_service_manager.py index ca076f2959f..8c37c3878bc 100644 --- a/tests/hermes_cli/test_service_manager.py +++ b/tests/hermes_cli/test_service_manager.py @@ -361,7 +361,6 @@ def test_get_service_manager_returns_s6_instance( ) -> None: """The s6 backend ships in Phase 3 — the factory must return an S6ServiceManager when running inside a container.""" - from hermes_cli.service_manager import S6ServiceManager monkeypatch.setattr( "hermes_cli.service_manager.detect_service_manager", lambda: "s6", ) @@ -406,7 +405,6 @@ def fake_subprocess_run(monkeypatch: pytest.MonkeyPatch): def test_s6_manager_kind_and_supports_registration() -> None: - from hermes_cli.service_manager import S6ServiceManager mgr = S6ServiceManager() assert mgr.kind == "s6" assert mgr.supports_runtime_registration() is True @@ -524,7 +522,6 @@ def test_seed_supervise_skeleton_is_idempotent(tmp_path) -> None: def test_s6_register_creates_service_dir_and_triggers_scan( s6_scandir, fake_subprocess_run, ) -> None: - from hermes_cli.service_manager import S6ServiceManager mgr = S6ServiceManager(scandir=s6_scandir) mgr.register_profile_gateway("coder") @@ -576,7 +573,6 @@ def test_s6_register_creates_service_dir_and_triggers_scan( def test_s6_register_extra_env_is_quoted(s6_scandir, fake_subprocess_run) -> None: - from hermes_cli.service_manager import S6ServiceManager mgr = S6ServiceManager(scandir=s6_scandir) mgr.register_profile_gateway( "x", extra_env={"FOO": "bar baz", "QUOTED": "a'b"}, @@ -588,7 +584,6 @@ def test_s6_register_extra_env_is_quoted(s6_scandir, fake_subprocess_run) -> Non def test_render_run_script_resets_home_before_exec() -> None: - from hermes_cli.service_manager import S6ServiceManager run_text = S6ServiceManager._render_run_script("coder", {}) @@ -597,14 +592,12 @@ def test_render_run_script_resets_home_before_exec() -> None: def test_s6_register_rejects_invalid_profile_name(s6_scandir) -> None: - from hermes_cli.service_manager import S6ServiceManager mgr = S6ServiceManager(scandir=s6_scandir) with pytest.raises(ValueError): mgr.register_profile_gateway("Bad/Name") def test_s6_register_rejects_duplicate(s6_scandir, fake_subprocess_run) -> None: - from hermes_cli.service_manager import S6ServiceManager mgr = S6ServiceManager(scandir=s6_scandir) (s6_scandir / "gateway-coder").mkdir(parents=True) with pytest.raises(ValueError, match="already registered"): @@ -617,7 +610,6 @@ def test_s6_register_rolls_back_on_svscanctl_failure( """If s6-svscanctl fails the service dir must be cleaned up so the next register call doesn't see a stale duplicate.""" import subprocess as _sp - from hermes_cli.service_manager import S6ServiceManager def _fail_scanctl(cmd, **kw): # Manager calls s6-svscanctl by absolute path; match on basename. @@ -635,7 +627,6 @@ def test_s6_register_rolls_back_on_svscanctl_failure( def test_s6_unregister_removes_service_dir( s6_scandir, fake_subprocess_run, ) -> None: - from hermes_cli.service_manager import S6ServiceManager svc_dir = s6_scandir / "gateway-coder" svc_dir.mkdir(parents=True) (svc_dir / "type").write_text("longrun\n") @@ -655,13 +646,11 @@ def test_s6_unregister_removes_service_dir( def test_s6_unregister_absent_profile_is_noop(s6_scandir) -> None: - from hermes_cli.service_manager import S6ServiceManager # Should NOT raise even though "ghost" doesn't exist S6ServiceManager(scandir=s6_scandir).unregister_profile_gateway("ghost") def test_s6_list_profile_gateways(s6_scandir) -> None: - from hermes_cli.service_manager import S6ServiceManager # Three gateway profiles + one unrelated service + one hidden dir (s6_scandir / "gateway-coder").mkdir() (s6_scandir / "gateway-assistant").mkdir() @@ -674,7 +663,6 @@ def test_s6_list_profile_gateways(s6_scandir) -> None: def test_s6_list_profile_gateways_empty_when_scandir_missing(tmp_path) -> None: - from hermes_cli.service_manager import S6ServiceManager missing = tmp_path / "does-not-exist" assert S6ServiceManager(scandir=missing).list_profile_gateways() == [] @@ -682,7 +670,6 @@ def test_s6_list_profile_gateways_empty_when_scandir_missing(tmp_path) -> None: def test_s6_lifecycle_dispatches_to_s6_svc( s6_scandir, fake_subprocess_run, ) -> None: - from hermes_cli.service_manager import S6ServiceManager mgr = S6ServiceManager(scandir=s6_scandir) # _run_svc now verifies the slot exists before invoking s6-svc, so # we have to pre-seed the dir. In real use the slot is created by @@ -710,7 +697,6 @@ def test_lifecycle_raises_gateway_not_registered_for_missing_slot( opaque CalledProcessError stacktrace.""" from hermes_cli.service_manager import ( GatewayNotRegisteredError, - S6ServiceManager, ) mgr = S6ServiceManager(scandir=s6_scandir) @@ -740,7 +726,6 @@ def test_all_lifecycle_methods_check_for_missing_slot( """start/stop/restart all check for missing slots the same way.""" from hermes_cli.service_manager import ( GatewayNotRegisteredError, - S6ServiceManager, ) mgr = S6ServiceManager(scandir=s6_scandir) @@ -755,7 +740,6 @@ def test_gateway_not_registered_unprefixed_service_name(s6_scandir) -> None: accidentally strip user-provided text.""" from hermes_cli.service_manager import ( GatewayNotRegisteredError, - S6ServiceManager, ) mgr = S6ServiceManager(scandir=s6_scandir) @@ -772,7 +756,7 @@ def test_lifecycle_raises_s6_command_error_on_subprocess_failure( CalledProcessError into a named S6CommandError carrying the return code and stderr.""" import subprocess as _sp - from hermes_cli.service_manager import S6CommandError, S6ServiceManager + from hermes_cli.service_manager import S6CommandError # Pre-create the slot so we reach the s6-svc call. (s6_scandir / "gateway-coder").mkdir() @@ -801,7 +785,6 @@ def test_s6_is_running_parses_svstat( s6_scandir, monkeypatch: pytest.MonkeyPatch, ) -> None: import subprocess as _sp - from hermes_cli.service_manager import S6ServiceManager def _svstat(cmd, **kw): if cmd[0].endswith("/s6-svstat"): diff --git a/tests/hermes_cli/test_session_browse.py b/tests/hermes_cli/test_session_browse.py index a9d7153c83a..833729973ae 100644 --- a/tests/hermes_cli/test_session_browse.py +++ b/tests/hermes_cli/test_session_browse.py @@ -6,11 +6,9 @@ Covers: - Argument parser registration """ -import os import time -from unittest.mock import MagicMock, patch, call +from unittest.mock import MagicMock, patch -import pytest from hermes_cli.main import _session_browse_picker @@ -249,7 +247,6 @@ class TestCursesBrowse: def _run_with_keys(self, sessions, key_sequence): """Simulate running the curses picker with a given key sequence.""" - import curses # Build a mock stdscr that returns keys from the sequence mock_stdscr = MagicMock() @@ -305,7 +302,6 @@ class TestCursesBrowse: def test_type_to_filter_then_enter(self): """Typing characters filters the list, Enter selects from filtered.""" - import curses sessions = [ {"id": "s1", "source": "cli", "title": "Alpha project", "preview": "", "last_active": time.time()}, {"id": "s2", "source": "cli", "title": "Beta project", "preview": "", "last_active": time.time()}, @@ -325,7 +321,6 @@ class TestCursesBrowse: def test_backspace_removes_filter_char(self): """Backspace removes the last character from the filter.""" - import curses sessions = [ {"id": "s1", "source": "cli", "title": "Alpha", "preview": "", "last_active": time.time()}, {"id": "s2", "source": "cli", "title": "Beta", "preview": "", "last_active": time.time()}, @@ -337,7 +332,6 @@ class TestCursesBrowse: def test_escape_clears_filter_first(self): """First Esc clears the search text, second Esc exits.""" - import curses sessions = _make_sessions(3) # Type "ab" then Esc (clears filter) then Enter (selects first) keys = [ord('a'), ord('b'), 27, 10] @@ -391,11 +385,9 @@ class TestSessionBrowseArgparse: def test_browse_subcommand_exists(self): """hermes sessions browse should be parseable.""" - from hermes_cli.main import main as _main_entry # We can't run main(), but we can import and test the parser setup # by checking that argparse doesn't error on "sessions browse" - import argparse # Re-create the parser portion # Instead, let's just verify the import works and the function exists from hermes_cli.main import _session_browse_picker diff --git a/tests/hermes_cli/test_session_recap.py b/tests/hermes_cli/test_session_recap.py index 3998c06c61a..062988525f2 100644 --- a/tests/hermes_cli/test_session_recap.py +++ b/tests/hermes_cli/test_session_recap.py @@ -3,7 +3,6 @@ from __future__ import annotations import json -import pytest from hermes_cli.session_recap import build_recap diff --git a/tests/hermes_cli/test_set_config_value.py b/tests/hermes_cli/test_set_config_value.py index 21516083c66..d404549cf52 100644 --- a/tests/hermes_cli/test_set_config_value.py +++ b/tests/hermes_cli/test_set_config_value.py @@ -2,8 +2,7 @@ import argparse import os -from pathlib import Path -from unittest.mock import patch, call +from unittest.mock import patch import pytest diff --git a/tests/hermes_cli/test_setup.py b/tests/hermes_cli/test_setup.py index 8f9a8494cdc..abd26a0a306 100644 --- a/tests/hermes_cli/test_setup.py +++ b/tests/hermes_cli/test_setup.py @@ -1,12 +1,8 @@ """Tests for setup.py configuration flows.""" -import json -import os import sys import types -import pytest -from hermes_cli.auth import get_active_provider from hermes_cli.config import load_config, save_config from hermes_cli import setup as setup_mod from hermes_cli.setup import setup_model_provider diff --git a/tests/hermes_cli/test_setup_irc.py b/tests/hermes_cli/test_setup_irc.py index 1e5baa5cc0f..31b263fec35 100644 --- a/tests/hermes_cli/test_setup_irc.py +++ b/tests/hermes_cli/test_setup_irc.py @@ -6,7 +6,6 @@ interactive setup menus. """ import os -import pytest from gateway.platform_registry import PlatformEntry, platform_registry diff --git a/tests/hermes_cli/test_setup_matrix_e2ee.py b/tests/hermes_cli/test_setup_matrix_e2ee.py index d965e354ac4..cde7618ed12 100644 --- a/tests/hermes_cli/test_setup_matrix_e2ee.py +++ b/tests/hermes_cli/test_setup_matrix_e2ee.py @@ -1,7 +1,6 @@ """Test that setup.py has shutil available for Matrix E2EE auto-install.""" import ast -import pytest def _parse_setup_imports(): diff --git a/tests/hermes_cli/test_setup_noninteractive.py b/tests/hermes_cli/test_setup_noninteractive.py index 68f6bd5a203..083b3069c93 100644 --- a/tests/hermes_cli/test_setup_noninteractive.py +++ b/tests/hermes_cli/test_setup_noninteractive.py @@ -1,7 +1,7 @@ """Tests for non-interactive setup and first-run headless behavior.""" from argparse import Namespace -from unittest.mock import MagicMock, patch +from unittest.mock import patch import pytest from hermes_cli.config import DEFAULT_CONFIG, load_config, save_config diff --git a/tests/hermes_cli/test_setup_ollama_cloud_force_refresh.py b/tests/hermes_cli/test_setup_ollama_cloud_force_refresh.py index b0ae2196d1d..60f6ea99341 100644 --- a/tests/hermes_cli/test_setup_ollama_cloud_force_refresh.py +++ b/tests/hermes_cli/test_setup_ollama_cloud_force_refresh.py @@ -5,7 +5,6 @@ serving a stale cache (models.dev only, no live API probe) for up to an hour. from __future__ import annotations -from unittest.mock import patch def test_setup_ollama_cloud_passes_force_refresh(monkeypatch): diff --git a/tests/hermes_cli/test_skills_config.py b/tests/hermes_cli/test_skills_config.py index 9742f0ac6f1..7e2170a3e94 100644 --- a/tests/hermes_cli/test_skills_config.py +++ b/tests/hermes_cli/test_skills_config.py @@ -1,6 +1,5 @@ """Tests for hermes_cli/skills_config.py and skills_tool disabled filtering.""" -import pytest -from unittest.mock import patch, MagicMock +from unittest.mock import patch # --------------------------------------------------------------------------- diff --git a/tests/hermes_cli/test_skills_install_flags.py b/tests/hermes_cli/test_skills_install_flags.py index b1608903fc6..bb8628c6700 100644 --- a/tests/hermes_cli/test_skills_install_flags.py +++ b/tests/hermes_cli/test_skills_install_flags.py @@ -8,7 +8,6 @@ Based on PR #1595 by 333Alden333 (salvaged). """ import sys -from types import SimpleNamespace def test_cli_skills_install_yes_sets_skip_confirm(monkeypatch): diff --git a/tests/hermes_cli/test_skills_skip_confirm.py b/tests/hermes_cli/test_skills_skip_confirm.py index fd430185f78..507d9115932 100644 --- a/tests/hermes_cli/test_skills_skip_confirm.py +++ b/tests/hermes_cli/test_skills_skip_confirm.py @@ -10,9 +10,8 @@ Based on PR #1595 by 333Alden333 (salvaged). Updated for PR #3586 (cache-aware install/uninstall). """ -from unittest.mock import patch, MagicMock +from unittest.mock import patch -import pytest class TestHandleSkillsSlashInstallFlags: diff --git a/tests/hermes_cli/test_skills_subparser.py b/tests/hermes_cli/test_skills_subparser.py index d2b89ed3eaa..853e422b9e0 100644 --- a/tests/hermes_cli/test_skills_subparser.py +++ b/tests/hermes_cli/test_skills_subparser.py @@ -17,7 +17,6 @@ def test_no_duplicate_skills_subparser(): # Force fresh import of the module where parser is constructed # If there are duplicate 'skills' subparsers, this import will raise # argparse.ArgumentError at module load time - import importlib import sys # Remove cached module if present diff --git a/tests/hermes_cli/test_skin_engine.py b/tests/hermes_cli/test_skin_engine.py index 0de68b5150b..ba4d4c4ce16 100644 --- a/tests/hermes_cli/test_skin_engine.py +++ b/tests/hermes_cli/test_skin_engine.py @@ -1,10 +1,6 @@ """Tests for hermes_cli.skin_engine — the data-driven skin/theme system.""" -import json -import os import pytest -from pathlib import Path -from unittest.mock import patch @pytest.fixture(autouse=True) @@ -185,7 +181,7 @@ class TestSkinManagement: class TestUserSkins: def test_load_user_skin_from_yaml(self, tmp_path, monkeypatch): - from hermes_cli.skin_engine import load_skin, _skins_dir + from hermes_cli.skin_engine import load_skin # Create a user skin YAML skins_dir = tmp_path / "skins" skins_dir.mkdir() diff --git a/tests/hermes_cli/test_subparser_routing_fallback.py b/tests/hermes_cli/test_subparser_routing_fallback.py index 37b3509f134..29c9b6a4b14 100644 --- a/tests/hermes_cli/test_subparser_routing_fallback.py +++ b/tests/hermes_cli/test_subparser_routing_fallback.py @@ -13,7 +13,6 @@ import argparse import io import sys -import pytest def _build_parser(): diff --git a/tests/hermes_cli/test_suppress_eio_on_interrupt.py b/tests/hermes_cli/test_suppress_eio_on_interrupt.py index a60ebef565e..0617bf1b403 100644 --- a/tests/hermes_cli/test_suppress_eio_on_interrupt.py +++ b/tests/hermes_cli/test_suppress_eio_on_interrupt.py @@ -13,7 +13,6 @@ to prevent a hard crash. from __future__ import annotations import errno -import os from unittest.mock import MagicMock import pytest diff --git a/tests/hermes_cli/test_tencent_tokenhub_provider.py b/tests/hermes_cli/test_tencent_tokenhub_provider.py index a673afc377e..55ab42244c8 100644 --- a/tests/hermes_cli/test_tencent_tokenhub_provider.py +++ b/tests/hermes_cli/test_tencent_tokenhub_provider.py @@ -10,7 +10,6 @@ from hermes_cli.auth import ( resolve_provider, get_api_key_provider_status, resolve_api_key_provider_credentials, - AuthError, ) diff --git a/tests/hermes_cli/test_tips.py b/tests/hermes_cli/test_tips.py index b0287df9647..31d0d116b26 100644 --- a/tests/hermes_cli/test_tips.py +++ b/tests/hermes_cli/test_tips.py @@ -1,6 +1,5 @@ """Tests for hermes_cli/tips.py — random tip display at session start.""" -import pytest from hermes_cli.tips import TIPS, get_random_tip diff --git a/tests/hermes_cli/test_tool_token_estimation.py b/tests/hermes_cli/test_tool_token_estimation.py index 3e48980bf88..87db30e628d 100644 --- a/tests/hermes_cli/test_tool_token_estimation.py +++ b/tests/hermes_cli/test_tool_token_estimation.py @@ -1,6 +1,5 @@ """Tests for tool token estimation and curses_ui status_fn support.""" -from unittest.mock import patch import pytest @@ -20,7 +19,7 @@ _needs_tiktoken = pytest.mark.skipif(not _has_tiktoken, reason="tiktoken not ins @_needs_tiktoken def test_estimate_tool_tokens_returns_positive_counts(): """_estimate_tool_tokens should return a non-empty dict with positive values.""" - from hermes_cli.tools_config import _estimate_tool_tokens, _tool_token_cache + from hermes_cli.tools_config import _estimate_tool_tokens # Clear cache to force fresh computation import hermes_cli.tools_config as tc diff --git a/tests/hermes_cli/test_tui_bundled.py b/tests/hermes_cli/test_tui_bundled.py index c49443a3f76..a5b97c2fa07 100644 --- a/tests/hermes_cli/test_tui_bundled.py +++ b/tests/hermes_cli/test_tui_bundled.py @@ -1,4 +1,3 @@ -from pathlib import Path def test_tui_finds_bundled_entry_js(tmp_path): diff --git a/tests/hermes_cli/test_update_hangup_protection.py b/tests/hermes_cli/test_update_hangup_protection.py index e5c81a45a01..5f91764b822 100644 --- a/tests/hermes_cli/test_update_hangup_protection.py +++ b/tests/hermes_cli/test_update_hangup_protection.py @@ -9,11 +9,8 @@ that ``hermes update`` survives a terminal disconnect mid-install from __future__ import annotations import io -import os import signal import sys -from pathlib import Path -from unittest.mock import patch import pytest diff --git a/tests/hermes_cli/test_update_stale_dashboard.py b/tests/hermes_cli/test_update_stale_dashboard.py index e79caeb9dc6..8a04d9cbe8e 100644 --- a/tests/hermes_cli/test_update_stale_dashboard.py +++ b/tests/hermes_cli/test_update_stale_dashboard.py @@ -16,7 +16,7 @@ from __future__ import annotations import importlib import os import sys -from unittest.mock import patch, MagicMock, call +from unittest.mock import patch, MagicMock import pytest diff --git a/tests/hermes_cli/test_update_zip_symlink_reject.py b/tests/hermes_cli/test_update_zip_symlink_reject.py index 2585b53fa7a..4ee7f84549b 100644 --- a/tests/hermes_cli/test_update_zip_symlink_reject.py +++ b/tests/hermes_cli/test_update_zip_symlink_reject.py @@ -7,7 +7,6 @@ The Linux mode bits live in the upper 16 bits of ``ZipInfo.external_attr``; we explicitly reject any member whose type bits are S_IFLNK. """ -import io import os import stat import tempfile diff --git a/tests/hermes_cli/test_web_server.py b/tests/hermes_cli/test_web_server.py index 30dc4fc05bd..23dde91ad8a 100644 --- a/tests/hermes_cli/test_web_server.py +++ b/tests/hermes_cli/test_web_server.py @@ -2,17 +2,13 @@ import os import json -import tempfile -from pathlib import Path from unittest.mock import patch, MagicMock import pytest from hermes_cli.config import ( - DEFAULT_CONFIG, reload_env, redact_key, - _EXTRA_ENV_KEYS, OPTIONAL_ENV_VARS, ) @@ -1918,7 +1914,6 @@ class TestPluginAPIAuth: shared layer can't silently break the WS auth contract. """ from starlette.websockets import WebSocketDisconnect - from hermes_cli.web_server import _SESSION_TOKEN # Without a token the WS endpoint must close the upgrade itself # (its own _check_ws_token), NOT 401 from the HTTP middleware. diff --git a/tests/hermes_cli/test_web_ui_build.py b/tests/hermes_cli/test_web_ui_build.py index 5288ca32592..bf887955a5a 100644 --- a/tests/hermes_cli/test_web_ui_build.py +++ b/tests/hermes_cli/test_web_ui_build.py @@ -11,7 +11,6 @@ import time from pathlib import Path from unittest.mock import patch -import pytest from hermes_cli.main import _web_ui_build_needed, _build_web_ui, _run_npm_install_deterministic diff --git a/tests/hermes_cli/test_webhook_cli.py b/tests/hermes_cli/test_webhook_cli.py index 8d3880722bb..46f6da84980 100644 --- a/tests/hermes_cli/test_webhook_cli.py +++ b/tests/hermes_cli/test_webhook_cli.py @@ -5,14 +5,12 @@ import os import pytest import stat from argparse import Namespace -from pathlib import Path from hermes_cli.webhook import ( webhook_command, _load_subscriptions, _save_subscriptions, _subscriptions_path, - _is_webhook_enabled, ) diff --git a/tests/hermes_cli/test_whatsapp_setup_ordering.py b/tests/hermes_cli/test_whatsapp_setup_ordering.py index 47952bcc796..0585bd0ff36 100644 --- a/tests/hermes_cli/test_whatsapp_setup_ordering.py +++ b/tests/hermes_cli/test_whatsapp_setup_ordering.py @@ -17,7 +17,7 @@ import io import os from contextlib import redirect_stdout from pathlib import Path -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock import pytest diff --git a/tests/hermes_cli/test_xai_retirement.py b/tests/hermes_cli/test_xai_retirement.py index c87214ff0f0..fd1884b0d08 100644 --- a/tests/hermes_cli/test_xai_retirement.py +++ b/tests/hermes_cli/test_xai_retirement.py @@ -1,7 +1,6 @@ """Unit tests for hermes_cli.xai_retirement (May 15, 2026 model retirement).""" from __future__ import annotations -import pytest from hermes_cli.xai_retirement import ( MIGRATION_GUIDE_URL, diff --git a/tests/hermes_cli/test_xiaomi_provider.py b/tests/hermes_cli/test_xiaomi_provider.py index 776e42201f2..4a5a7724ad0 100644 --- a/tests/hermes_cli/test_xiaomi_provider.py +++ b/tests/hermes_cli/test_xiaomi_provider.py @@ -1,6 +1,5 @@ """Tests for Xiaomi MiMo provider support.""" -import os import pytest @@ -9,7 +8,6 @@ from hermes_cli.auth import ( resolve_provider, get_api_key_provider_status, resolve_api_key_provider_credentials, - AuthError, ) diff --git a/tests/honcho_plugin/test_async_memory.py b/tests/honcho_plugin/test_async_memory.py index 5df8d274540..97f4f7306d5 100644 --- a/tests/honcho_plugin/test_async_memory.py +++ b/tests/honcho_plugin/test_async_memory.py @@ -10,19 +10,14 @@ Covers: """ import json -import queue -import threading import time -from pathlib import Path -from unittest.mock import MagicMock, patch, call +from unittest.mock import MagicMock, patch -import pytest from plugins.memory.honcho.client import HonchoClientConfig from plugins.memory.honcho.session import ( HonchoSession, HonchoSessionManager, - _ASYNC_SHUTDOWN, ) diff --git a/tests/honcho_plugin/test_client.py b/tests/honcho_plugin/test_client.py index b6530db9f84..a02e6937a34 100644 --- a/tests/honcho_plugin/test_client.py +++ b/tests/honcho_plugin/test_client.py @@ -17,7 +17,6 @@ from plugins.memory.honcho.client import ( resolve_active_host, resolve_config_path, resolve_global_config_path, - HOST, ) diff --git a/tests/honcho_plugin/test_pin_peer_name.py b/tests/honcho_plugin/test_pin_peer_name.py index d3d935f9a05..ef3a215f329 100644 --- a/tests/honcho_plugin/test_pin_peer_name.py +++ b/tests/honcho_plugin/test_pin_peer_name.py @@ -18,7 +18,6 @@ import hashlib import json from unittest.mock import MagicMock -import pytest from plugins.memory.honcho.client import HonchoClientConfig from plugins.memory.honcho.session import HonchoSessionManager diff --git a/tests/honcho_plugin/test_session.py b/tests/honcho_plugin/test_session.py index cd9670af237..cf47f3a38bb 100644 --- a/tests/honcho_plugin/test_session.py +++ b/tests/honcho_plugin/test_session.py @@ -1237,7 +1237,6 @@ class TestDialecticCadenceAdvancesOnSuccess: return provider def test_empty_dialectic_result_does_not_advance_cadence(self): - import time as _time provider = self._make_provider() provider._session_key = "test" provider._manager.dialectic_query.return_value = "" # silent failure diff --git a/tests/integration/test_checkpoint_resumption.py b/tests/integration/test_checkpoint_resumption.py index a5b1a2aa99f..739f0452fe3 100644 --- a/tests/integration/test_checkpoint_resumption.py +++ b/tests/integration/test_checkpoint_resumption.py @@ -22,7 +22,6 @@ import pytest pytestmark = pytest.mark.integration import json -import os import shutil import sys import time diff --git a/tests/integration/test_voice_channel_flow.py b/tests/integration/test_voice_channel_flow.py index 420adcb0e73..4c6d5ae11cb 100644 --- a/tests/integration/test_voice_channel_flow.py +++ b/tests/integration/test_voice_channel_flow.py @@ -24,7 +24,6 @@ try: import ctypes.util opus_path = ctypes.util.find_library("opus") if not opus_path: - import sys for p in ("/opt/homebrew/lib/libopus.dylib", "/usr/local/lib/libopus.dylib"): import os if os.path.isfile(p): diff --git a/tests/plugins/image_gen/test_fal_provider.py b/tests/plugins/image_gen/test_fal_provider.py index 8b3e65e0bae..a75c3da547e 100644 --- a/tests/plugins/image_gen/test_fal_provider.py +++ b/tests/plugins/image_gen/test_fal_provider.py @@ -16,7 +16,6 @@ from __future__ import annotations import json from unittest.mock import MagicMock -import pytest # --------------------------------------------------------------------------- diff --git a/tests/plugins/image_gen/test_openai_provider.py b/tests/plugins/image_gen/test_openai_provider.py index 6411996130e..8a6a4985014 100644 --- a/tests/plugins/image_gen/test_openai_provider.py +++ b/tests/plugins/image_gen/test_openai_provider.py @@ -137,7 +137,6 @@ class TestGenerate: assert result["error_type"] == "auth_required" def test_b64_saves_to_cache(self, provider, tmp_path): - import base64 png_bytes = bytes.fromhex(_PNG_HEX) fake_client = MagicMock() fake_client.images.generate.return_value = _fake_response(b64=_b64_png()) diff --git a/tests/plugins/image_gen/test_xai_provider.py b/tests/plugins/image_gen/test_xai_provider.py index f921fe2e291..d1e7beab15e 100644 --- a/tests/plugins/image_gen/test_xai_provider.py +++ b/tests/plugins/image_gen/test_xai_provider.py @@ -4,7 +4,6 @@ from __future__ import annotations import json -import os from pathlib import Path from unittest.mock import MagicMock, patch diff --git a/tests/plugins/memory/test_hindsight_provider.py b/tests/plugins/memory/test_hindsight_provider.py index 72ffe9e6f11..bc62b7f2c8f 100644 --- a/tests/plugins/memory/test_hindsight_provider.py +++ b/tests/plugins/memory/test_hindsight_provider.py @@ -1016,7 +1016,6 @@ class TestSessionSwitchBufferFlush: old session to settle before clearing _prefetch_result, otherwise the thread can race and re-populate the field after the clear.""" import threading - import time as _time gate = threading.Event() finished = threading.Event() diff --git a/tests/plugins/memory/test_mem0_v2.py b/tests/plugins/memory/test_mem0_v2.py index 6f60771f5c4..1ef85499b54 100644 --- a/tests/plugins/memory/test_mem0_v2.py +++ b/tests/plugins/memory/test_mem0_v2.py @@ -4,7 +4,6 @@ Salvaged from PRs #5301 (qaqcvc) and #5117 (vvvanguards). """ import json -import pytest from plugins.memory.mem0 import Mem0MemoryProvider diff --git a/tests/plugins/test_google_meet_audio.py b/tests/plugins/test_google_meet_audio.py index 9af0f76f81f..d5207518d8f 100644 --- a/tests/plugins/test_google_meet_audio.py +++ b/tests/plugins/test_google_meet_audio.py @@ -6,7 +6,6 @@ without actually invoking those tools on the host. from __future__ import annotations -import subprocess from unittest.mock import MagicMock, patch import pytest diff --git a/tests/plugins/test_google_meet_node.py b/tests/plugins/test_google_meet_node.py index bee1a184366..0a5ebc9aba6 100644 --- a/tests/plugins/test_google_meet_node.py +++ b/tests/plugins/test_google_meet_node.py @@ -12,7 +12,6 @@ import argparse import asyncio import json from pathlib import Path -from unittest.mock import MagicMock, patch import pytest diff --git a/tests/plugins/test_google_meet_plugin.py b/tests/plugins/test_google_meet_plugin.py index c8dacc81d24..92815553922 100644 --- a/tests/plugins/test_google_meet_plugin.py +++ b/tests/plugins/test_google_meet_plugin.py @@ -764,7 +764,6 @@ def test_cmd_install_refuses_windows(capsys): def test_cmd_install_runs_pip_and_playwright(capsys): """End-to-end wiring: pip + playwright install invoked, returncodes handled.""" from plugins.google_meet.cli import _cmd_install - import subprocess as _sp calls = [] class _FakeRes: diff --git a/tests/plugins/test_google_meet_realtime.py b/tests/plugins/test_google_meet_realtime.py index 71d02216937..1f3f0c9c033 100644 --- a/tests/plugins/test_google_meet_realtime.py +++ b/tests/plugins/test_google_meet_realtime.py @@ -8,10 +8,7 @@ from __future__ import annotations import base64 import json import sys -import threading import types -from pathlib import Path -from unittest.mock import patch import pytest diff --git a/tests/plugins/test_kanban_dashboard_plugin.py b/tests/plugins/test_kanban_dashboard_plugin.py index 5fa1881fa32..57ce67352e4 100644 --- a/tests/plugins/test_kanban_dashboard_plugin.py +++ b/tests/plugins/test_kanban_dashboard_plugin.py @@ -835,8 +835,6 @@ def test_ws_events_swallows_cancellation_on_shutdown(tmp_path, monkeypatch): the cancellation outcome deterministically. """ import asyncio - import types - import sys as _sys home = tmp_path / ".hermes" home.mkdir() diff --git a/tests/plugins/test_kanban_worker_runs.py b/tests/plugins/test_kanban_worker_runs.py index ba84d9ea9a8..3e79abbd2fa 100644 --- a/tests/plugins/test_kanban_worker_runs.py +++ b/tests/plugins/test_kanban_worker_runs.py @@ -13,7 +13,7 @@ import secrets import sys import time from pathlib import Path -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock import pytest from fastapi import FastAPI diff --git a/tests/plugins/test_retaindb_plugin.py b/tests/plugins/test_retaindb_plugin.py index 5d517bce776..11fba5b15cf 100644 --- a/tests/plugins/test_retaindb_plugin.py +++ b/tests/plugins/test_retaindb_plugin.py @@ -5,13 +5,10 @@ RetainDBMemoryProvider lifecycle/tools/prefetch, thread management, connection p """ import json -import os import sqlite3 -import tempfile -import threading import time from pathlib import Path -from unittest.mock import MagicMock, patch, PropertyMock +from unittest.mock import MagicMock, patch import pytest @@ -67,8 +64,6 @@ from plugins.memory.retaindb import ( _WriteQueue, _build_overlay, RetainDBMemoryProvider, - _ASYNC_SHUTDOWN, - _DEFAULT_BASE_URL, ) diff --git a/tests/plugins/test_security_guidance_plugin.py b/tests/plugins/test_security_guidance_plugin.py index c4f551fba2c..10efa1061b2 100644 --- a/tests/plugins/test_security_guidance_plugin.py +++ b/tests/plugins/test_security_guidance_plugin.py @@ -16,9 +16,7 @@ Covers ``plugins/security-guidance/``: * Bundled-plugin discovery via ``PluginManager.discover_and_load``. """ -import importlib import importlib.util -import json import sys import types from pathlib import Path diff --git a/tests/plugins/test_teams_pipeline_plugin.py b/tests/plugins/test_teams_pipeline_plugin.py index 862b5399720..e0bc978cefa 100644 --- a/tests/plugins/test_teams_pipeline_plugin.py +++ b/tests/plugins/test_teams_pipeline_plugin.py @@ -5,7 +5,6 @@ from __future__ import annotations import asyncio from types import SimpleNamespace from pathlib import Path -from unittest.mock import MagicMock import pytest diff --git a/tests/plugins/web/test_web_search_provider_plugins.py b/tests/plugins/web/test_web_search_provider_plugins.py index 60f8463fd37..2177d875c4b 100644 --- a/tests/plugins/web/test_web_search_provider_plugins.py +++ b/tests/plugins/web/test_web_search_provider_plugins.py @@ -20,9 +20,6 @@ from __future__ import annotations import asyncio import inspect -import os -import sys -from typing import Any, Dict, List import pytest @@ -268,7 +265,7 @@ class TestRegistryResolution: surfaces a precise "FOO_API_KEY is not set" error instead. """ _ensure_plugins_loaded() - from agent.web_search_registry import _resolve, get_provider + from agent.web_search_registry import _resolve # No BRAVE_SEARCH_API_KEY (fixture cleared it). result = _resolve("brave-free", capability="search") diff --git a/tests/providers/test_plugin_discovery.py b/tests/providers/test_plugin_discovery.py index be5c56122ea..fba5a02df11 100644 --- a/tests/providers/test_plugin_discovery.py +++ b/tests/providers/test_plugin_discovery.py @@ -8,11 +8,9 @@ Verifies that: from __future__ import annotations -import importlib import sys from pathlib import Path -import pytest REPO_ROOT = Path(__file__).resolve().parents[2] diff --git a/tests/providers/test_provider_profiles.py b/tests/providers/test_provider_profiles.py index 7a2bb081593..c9e9daa623d 100644 --- a/tests/providers/test_provider_profiles.py +++ b/tests/providers/test_provider_profiles.py @@ -1,6 +1,5 @@ """Tests for the provider module registry and profiles.""" -import pytest from providers import get_provider_profile, _REGISTRY from providers.base import ProviderProfile, OMIT_TEMPERATURE diff --git a/tests/run_agent/test_1630_context_overflow_loop.py b/tests/run_agent/test_1630_context_overflow_loop.py index f69b01241bb..3e5e3d0cfdf 100644 --- a/tests/run_agent/test_1630_context_overflow_loop.py +++ b/tests/run_agent/test_1630_context_overflow_loop.py @@ -8,8 +8,6 @@ Verifies that: 3. Context-overflow failures produce helpful error messages suggesting /compact. """ -import pytest -from types import SimpleNamespace from unittest.mock import MagicMock, patch diff --git a/tests/run_agent/test_413_compression.py b/tests/run_agent/test_413_compression.py index 82fc6b3e60d..6695d6c275e 100644 --- a/tests/run_agent/test_413_compression.py +++ b/tests/run_agent/test_413_compression.py @@ -11,11 +11,9 @@ import pytest -import uuid from types import SimpleNamespace from unittest.mock import MagicMock, patch -import pytest from agent.context_compressor import SUMMARY_PREFIX from run_agent import AIAgent diff --git a/tests/run_agent/test_860_dedup.py b/tests/run_agent/test_860_dedup.py index 070936af67b..39a7c0f3154 100644 --- a/tests/run_agent/test_860_dedup.py +++ b/tests/run_agent/test_860_dedup.py @@ -7,14 +7,11 @@ Verifies that: 4. The gateway doesn't double-write messages the agent already persisted """ -import json import os -import sqlite3 import tempfile from pathlib import Path -from unittest.mock import MagicMock, patch +from unittest.mock import patch -import pytest # --------------------------------------------------------------------------- diff --git a/tests/run_agent/test_api_max_retries_config.py b/tests/run_agent/test_api_max_retries_config.py index 44e859986ba..5ef7ee4b044 100644 --- a/tests/run_agent/test_api_max_retries_config.py +++ b/tests/run_agent/test_api_max_retries_config.py @@ -4,7 +4,7 @@ Closes #11616 — make the hardcoded ``max_retries = 3`` in the agent's API retry loop user-configurable so fallback-provider setups can fail over faster on flaky primaries instead of burning ~3x180s on the same stall. """ -from unittest.mock import MagicMock, patch +from unittest.mock import patch from run_agent import AIAgent diff --git a/tests/run_agent/test_async_httpx_del_neuter.py b/tests/run_agent/test_async_httpx_del_neuter.py index e91102288c0..946d73dbdf1 100644 --- a/tests/run_agent/test_async_httpx_del_neuter.py +++ b/tests/run_agent/test_async_httpx_del_neuter.py @@ -13,8 +13,6 @@ The three-layer defence: """ import asyncio -import threading -from types import SimpleNamespace from unittest.mock import MagicMock, patch import pytest diff --git a/tests/run_agent/test_background_review_toolset_restriction.py b/tests/run_agent/test_background_review_toolset_restriction.py index 9682014ee44..f94ef831ae9 100644 --- a/tests/run_agent/test_background_review_toolset_restriction.py +++ b/tests/run_agent/test_background_review_toolset_restriction.py @@ -13,7 +13,6 @@ runtime via a thread-local whitelist on the existing that caused the prefix-cache miss. """ -import threading from unittest.mock import patch diff --git a/tests/run_agent/test_callable_api_key.py b/tests/run_agent/test_callable_api_key.py index 2c685643b98..9bd14462827 100644 --- a/tests/run_agent/test_callable_api_key.py +++ b/tests/run_agent/test_callable_api_key.py @@ -26,9 +26,8 @@ Covered: from __future__ import annotations import json -from types import SimpleNamespace from typing import cast -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock import pytest diff --git a/tests/run_agent/test_codex_no_tools_nonetype.py b/tests/run_agent/test_codex_no_tools_nonetype.py index d7980e8f02e..7c4aa43f613 100644 --- a/tests/run_agent/test_codex_no_tools_nonetype.py +++ b/tests/run_agent/test_codex_no_tools_nonetype.py @@ -29,7 +29,6 @@ from __future__ import annotations import sys import types -from types import SimpleNamespace from typing import Any, Dict, List import pytest diff --git a/tests/run_agent/test_codex_xai_oauth_recovery.py b/tests/run_agent/test_codex_xai_oauth_recovery.py index 170dabb3069..a82eb7e62c0 100644 --- a/tests/run_agent/test_codex_xai_oauth_recovery.py +++ b/tests/run_agent/test_codex_xai_oauth_recovery.py @@ -31,7 +31,7 @@ Three distinct failure modes the user community hit during rollout: """ from types import SimpleNamespace -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock import pytest @@ -500,7 +500,6 @@ def test_recover_with_credential_pool_skips_refresh_on_entitlement_403(): the entitlement guard, recovery returns False so the error surfaces normally with the friendly hint from _summarize_api_error. """ - from run_agent import AIAgent from agent.error_classifier import FailoverReason agent = _make_codex_agent() @@ -590,7 +589,6 @@ def test_recover_with_credential_pool_skips_refresh_on_bare_403_for_xai_oauth(): def test_recover_with_credential_pool_still_refreshes_genuine_auth_failure(): """Regression guard: legitimate auth errors must still trigger refresh.""" - from run_agent import AIAgent from agent.error_classifier import FailoverReason agent = _make_codex_agent() @@ -772,7 +770,6 @@ def test_recover_with_credential_pool_refreshes_on_xai_bad_credentials_403(): the very body that pre-fix tripped the entitlement classifier and short-circuited the refresh path. """ - from run_agent import AIAgent from agent.error_classifier import FailoverReason agent = _make_codex_agent() @@ -829,7 +826,6 @@ def test_recover_with_credential_pool_still_blocks_real_entitlement(): survive the new disambiguator. A real unsubscribed-account body has no WKE suffix and no OAuth2-validation phrase, so the classifier still classifies it as entitlement and short-circuits.""" - from run_agent import AIAgent from agent.error_classifier import FailoverReason agent = _make_codex_agent() diff --git a/tests/run_agent/test_compress_focus_plugin_fallback.py b/tests/run_agent/test_compress_focus_plugin_fallback.py index f9c1b83dcc0..1a16f82abd4 100644 --- a/tests/run_agent/test_compress_focus_plugin_fallback.py +++ b/tests/run_agent/test_compress_focus_plugin_fallback.py @@ -9,7 +9,6 @@ on older plugins. from unittest.mock import MagicMock -import pytest from run_agent import AIAgent diff --git a/tests/run_agent/test_compression_boundary.py b/tests/run_agent/test_compression_boundary.py index db7bb67b80f..ff9455d75c2 100644 --- a/tests/run_agent/test_compression_boundary.py +++ b/tests/run_agent/test_compression_boundary.py @@ -4,8 +4,7 @@ Verifies that _align_boundary_backward correctly handles tool result groups so that parallel tool calls are never split during compression. """ -import pytest -from unittest.mock import patch, MagicMock +from unittest.mock import patch from agent.context_compressor import ContextCompressor diff --git a/tests/run_agent/test_compression_boundary_hook.py b/tests/run_agent/test_compression_boundary_hook.py index ef06e97e369..fba465bb264 100644 --- a/tests/run_agent/test_compression_boundary_hook.py +++ b/tests/run_agent/test_compression_boundary_hook.py @@ -16,7 +16,6 @@ import tempfile from pathlib import Path from unittest.mock import MagicMock, patch -import pytest class TestCompressionBoundaryHook: diff --git a/tests/run_agent/test_compression_persistence.py b/tests/run_agent/test_compression_persistence.py index 46ab963d420..e8b20487cd4 100644 --- a/tests/run_agent/test_compression_persistence.py +++ b/tests/run_agent/test_compression_persistence.py @@ -19,9 +19,8 @@ Bug scenario (pre-fix): import os import tempfile from pathlib import Path -from unittest.mock import MagicMock, patch +from unittest.mock import patch -import pytest # --------------------------------------------------------------------------- diff --git a/tests/run_agent/test_compression_trigger_excludes_reasoning.py b/tests/run_agent/test_compression_trigger_excludes_reasoning.py index 24fe2868fcb..22fb37bf525 100644 --- a/tests/run_agent/test_compression_trigger_excludes_reasoning.py +++ b/tests/run_agent/test_compression_trigger_excludes_reasoning.py @@ -6,8 +6,6 @@ trigger must use only prompt_tokens so sessions aren't prematurely split. """ import types -import pytest -from unittest.mock import MagicMock, patch def _make_agent_stub(prompt_tokens, completion_tokens, threshold_tokens): diff --git a/tests/run_agent/test_concurrent_interrupt.py b/tests/run_agent/test_concurrent_interrupt.py index 747ecb7ca2e..4cb35695c0b 100644 --- a/tests/run_agent/test_concurrent_interrupt.py +++ b/tests/run_agent/test_concurrent_interrupt.py @@ -1,9 +1,8 @@ """Tests for interrupt handling in concurrent tool execution.""" -import concurrent.futures import threading import time -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock import pytest diff --git a/tests/run_agent/test_create_openai_client_reuse.py b/tests/run_agent/test_create_openai_client_reuse.py index 8b39711b3e4..a5e3fcb86dc 100644 --- a/tests/run_agent/test_create_openai_client_reuse.py +++ b/tests/run_agent/test_create_openai_client_reuse.py @@ -17,7 +17,7 @@ That is the exact scenario this test reproduces at object level without a network, so it runs in CI on every PR. """ from types import SimpleNamespace -from unittest.mock import MagicMock, patch +from unittest.mock import patch from run_agent import AIAgent diff --git a/tests/run_agent/test_credential_pool_interrupt.py b/tests/run_agent/test_credential_pool_interrupt.py index 8484fa003e9..8dab8da949a 100644 --- a/tests/run_agent/test_credential_pool_interrupt.py +++ b/tests/run_agent/test_credential_pool_interrupt.py @@ -3,7 +3,6 @@ When has_retried_429 is lost (user cancels between 429s), the pool should still rotate if the current credential is already marked exhausted. """ -import pytest from unittest.mock import MagicMock, patch from agent.credential_pool import PooledCredential, STATUS_EXHAUSTED diff --git a/tests/run_agent/test_exit_cleanup_interrupt.py b/tests/run_agent/test_exit_cleanup_interrupt.py index 1e5d8431c38..b8c6b661e02 100644 --- a/tests/run_agent/test_exit_cleanup_interrupt.py +++ b/tests/run_agent/test_exit_cleanup_interrupt.py @@ -6,9 +6,7 @@ abort remaining cleanup steps. These tests exercise the actual production code paths — not a copy of the try/except pattern. """ -import atexit -import weakref -from unittest.mock import MagicMock, patch, call +from unittest.mock import MagicMock, patch import pytest diff --git a/tests/run_agent/test_fallback_credential_isolation.py b/tests/run_agent/test_fallback_credential_isolation.py index a32eaa2a309..54e352b3b88 100644 --- a/tests/run_agent/test_fallback_credential_isolation.py +++ b/tests/run_agent/test_fallback_credential_isolation.py @@ -11,13 +11,9 @@ _swap_credential continue operating on the PRIMARY's credential pool during fallback calls, contaminating primary state with fallback-provider errors. """ -import logging import sys -import types -from dataclasses import dataclass, replace -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock -import pytest # ── Helpers ────────────────────────────────────────────────────────── diff --git a/tests/run_agent/test_image_shrink_recovery.py b/tests/run_agent/test_image_shrink_recovery.py index 7435bb7a13c..c5114ffef04 100644 --- a/tests/run_agent/test_image_shrink_recovery.py +++ b/tests/run_agent/test_image_shrink_recovery.py @@ -18,9 +18,7 @@ payload rewriter. from __future__ import annotations import base64 -from pathlib import Path -import pytest from agent.error_classifier import FailoverReason, classify_api_error diff --git a/tests/run_agent/test_interactive_interrupt.py b/tests/run_agent/test_interactive_interrupt.py index 762621f2203..27d3bff91c0 100644 --- a/tests/run_agent/test_interactive_interrupt.py +++ b/tests/run_agent/test_interactive_interrupt.py @@ -8,9 +8,6 @@ Logs every step to stderr (which isn't affected by redirect_stdout) so we can see exactly where the interrupt gets lost. """ -import contextlib -import io -import json import logging import queue import sys @@ -27,7 +24,7 @@ sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspa from unittest.mock import MagicMock, patch from run_agent import AIAgent, IterationBudget -from tools.interrupt import set_interrupt, is_interrupted +from tools.interrupt import set_interrupt def make_slow_response(delay=2.0): """API response that takes a while.""" diff --git a/tests/run_agent/test_interrupt_propagation.py b/tests/run_agent/test_interrupt_propagation.py index 9dd8ce327e6..7e3085f1d2c 100644 --- a/tests/run_agent/test_interrupt_propagation.py +++ b/tests/run_agent/test_interrupt_propagation.py @@ -4,13 +4,12 @@ Reproduces the CLI scenario: user sends a message while delegate_task is running, main thread calls parent.interrupt(), child should stop. """ -import json import threading import time import unittest -from unittest.mock import MagicMock, patch, PropertyMock +from unittest.mock import MagicMock -from tools.interrupt import set_interrupt, is_interrupted, _interrupt_event +from tools.interrupt import set_interrupt, is_interrupted class TestInterruptPropagationToChild(unittest.TestCase): diff --git a/tests/run_agent/test_invalid_context_length_warning.py b/tests/run_agent/test_invalid_context_length_warning.py index 14b2e0f2a15..a38980e9774 100644 --- a/tests/run_agent/test_invalid_context_length_warning.py +++ b/tests/run_agent/test_invalid_context_length_warning.py @@ -1,6 +1,6 @@ """Tests that invalid context_length values in config produce visible warnings.""" -from unittest.mock import patch, MagicMock, call +from unittest.mock import patch def _build_agent(model_cfg, custom_providers=None, model="anthropic/claude-opus-4.6"): diff --git a/tests/run_agent/test_iteration_budget_race.py b/tests/run_agent/test_iteration_budget_race.py index e8aa70fbf6f..9b75b1f4c5b 100644 --- a/tests/run_agent/test_iteration_budget_race.py +++ b/tests/run_agent/test_iteration_budget_race.py @@ -3,11 +3,8 @@ The `used` property must acquire the lock before reading `_used` to prevent data races with concurrent `consume()` / `refund()` calls. """ -import threading -import time from concurrent.futures import ThreadPoolExecutor -import pytest def test_iteration_budget_used_is_thread_safe(): diff --git a/tests/run_agent/test_long_context_tier_429.py b/tests/run_agent/test_long_context_tier_429.py index 07e569bed95..79185cfbb74 100644 --- a/tests/run_agent/test_long_context_tier_429.py +++ b/tests/run_agent/test_long_context_tier_429.py @@ -8,9 +8,7 @@ reduce context_length to 200k and compress instead of retrying. Only Sonnet is affected — Opus 1M is general access. """ -import pytest from types import SimpleNamespace -from unittest.mock import MagicMock, patch # --------------------------------------------------------------------------- diff --git a/tests/run_agent/test_multimodal_tool_content_recovery.py b/tests/run_agent/test_multimodal_tool_content_recovery.py index 63ee49f97c0..0d9deef9394 100644 --- a/tests/run_agent/test_multimodal_tool_content_recovery.py +++ b/tests/run_agent/test_multimodal_tool_content_recovery.py @@ -25,7 +25,6 @@ See: https://github.com/NousResearch/hermes-agent/issues/27344 from __future__ import annotations -import pytest from agent.error_classifier import FailoverReason, classify_api_error diff --git a/tests/run_agent/test_primary_runtime_restore.py b/tests/run_agent/test_primary_runtime_restore.py index b921e61ab14..07fdecce8c6 100644 --- a/tests/run_agent/test_primary_runtime_restore.py +++ b/tests/run_agent/test_primary_runtime_restore.py @@ -10,10 +10,8 @@ Verifies that: """ import time -from types import SimpleNamespace -from unittest.mock import MagicMock, patch, PropertyMock +from unittest.mock import MagicMock, patch -import pytest from run_agent import AIAgent diff --git a/tests/run_agent/test_provider_parity.py b/tests/run_agent/test_provider_parity.py index f0e1aadb51d..4b80d2e1b76 100644 --- a/tests/run_agent/test_provider_parity.py +++ b/tests/run_agent/test_provider_parity.py @@ -4,12 +4,10 @@ and handles responses properly for all supported providers. Ensures changes to one provider path don't silently break another. """ -import json -import os import sys import types from types import SimpleNamespace -from unittest.mock import patch, MagicMock +from unittest.mock import patch import pytest from agent.codex_responses_adapter import _chat_content_to_responses_parts, _chat_messages_to_responses_input, _normalize_codex_response, _preflight_codex_input_items diff --git a/tests/run_agent/test_real_interrupt_subagent.py b/tests/run_agent/test_real_interrupt_subagent.py index 39b4c58e2d4..a76fb3f84fb 100644 --- a/tests/run_agent/test_real_interrupt_subagent.py +++ b/tests/run_agent/test_real_interrupt_subagent.py @@ -4,14 +4,13 @@ This uses a real AIAgent with mocked HTTP responses to test the complete interrupt flow through _run_single_child → child.run_conversation(). """ -import json import os import threading import time import unittest -from unittest.mock import MagicMock, patch, PropertyMock +from unittest.mock import MagicMock, patch -from tools.interrupt import set_interrupt, is_interrupted +from tools.interrupt import set_interrupt def _make_slow_api_response(delay=5.0): diff --git a/tests/run_agent/test_repair_tool_call_arguments.py b/tests/run_agent/test_repair_tool_call_arguments.py index c282397fccd..dcd98b5acff 100644 --- a/tests/run_agent/test_repair_tool_call_arguments.py +++ b/tests/run_agent/test_repair_tool_call_arguments.py @@ -1,7 +1,6 @@ """Tests for _repair_tool_call_arguments — malformed JSON repair pipeline.""" import json -import pytest from run_agent import _repair_tool_call_arguments diff --git a/tests/run_agent/test_retry_status_buffer.py b/tests/run_agent/test_retry_status_buffer.py index a47f19fa502..221c10c7596 100644 --- a/tests/run_agent/test_retry_status_buffer.py +++ b/tests/run_agent/test_retry_status_buffer.py @@ -8,7 +8,6 @@ silently dropped. from __future__ import annotations -import pytest from run_agent import AIAgent diff --git a/tests/run_agent/test_run_agent.py b/tests/run_agent/test_run_agent.py index 70d5abf42b5..f2efe04c6e5 100644 --- a/tests/run_agent/test_run_agent.py +++ b/tests/run_agent/test_run_agent.py @@ -16,7 +16,7 @@ from types import SimpleNamespace from unittest.mock import AsyncMock, MagicMock, patch import pytest -from agent.codex_responses_adapter import _chat_messages_to_responses_input, _normalize_codex_response, _preflight_codex_input_items +from agent.codex_responses_adapter import _normalize_codex_response import run_agent from run_agent import AIAgent @@ -4630,7 +4630,6 @@ class TestSafeWriter: def test_double_wrap_prevented(self): """Wrapping an already-wrapped stream doesn't add layers.""" - import sys from run_agent import _SafeWriter from io import StringIO inner = StringIO() diff --git a/tests/run_agent/test_session_meta_filtering.py b/tests/run_agent/test_session_meta_filtering.py index 08fc96e9fe4..23628b8848a 100644 --- a/tests/run_agent/test_session_meta_filtering.py +++ b/tests/run_agent/test_session_meta_filtering.py @@ -6,8 +6,6 @@ _sanitize_api_messages() and the CLI session-restore paths. """ import logging -import types -from unittest.mock import MagicMock, patch from run_agent import AIAgent diff --git a/tests/run_agent/test_session_reset_fix.py b/tests/run_agent/test_session_reset_fix.py index 1fd1223ced2..2b86642fd41 100644 --- a/tests/run_agent/test_session_reset_fix.py +++ b/tests/run_agent/test_session_reset_fix.py @@ -10,7 +10,6 @@ import sys import types from pathlib import Path -import pytest # Ensure repo root is importable sys.path.insert(0, str(Path(__file__).resolve().parent.parent.parent)) diff --git a/tests/run_agent/test_steer.py b/tests/run_agent/test_steer.py index d99a0af8057..42f3ada985d 100644 --- a/tests/run_agent/test_steer.py +++ b/tests/run_agent/test_steer.py @@ -281,7 +281,7 @@ class TestSteerCommandRegistry: """The /steer slash command must be registered so it reaches all platforms (CLI, gateway, TUI autocomplete, Telegram/Slack menus). """ - from hermes_cli.commands import resolve_command, ACTIVE_SESSION_BYPASS_COMMANDS + from hermes_cli.commands import resolve_command cmd = resolve_command("steer") assert cmd is not None diff --git a/tests/run_agent/test_stream_drop_logging.py b/tests/run_agent/test_stream_drop_logging.py index bcb6ddd1a12..3ba6400a7da 100644 --- a/tests/run_agent/test_stream_drop_logging.py +++ b/tests/run_agent/test_stream_drop_logging.py @@ -21,9 +21,7 @@ import logging import time from unittest.mock import patch -import pytest -import run_agent from run_agent import AIAgent diff --git a/tests/run_agent/test_streaming.py b/tests/run_agent/test_streaming.py index cfd8621842c..79c241adffa 100644 --- a/tests/run_agent/test_streaming.py +++ b/tests/run_agent/test_streaming.py @@ -3,11 +3,8 @@ Tests the unified streaming API call, delta callbacks, tool-call suppression, provider fallback, and CLI streaming display. """ -import json -import threading -import uuid from types import SimpleNamespace -from unittest.mock import MagicMock, patch, PropertyMock +from unittest.mock import MagicMock, patch import pytest diff --git a/tests/run_agent/test_streaming_tool_call_repair.py b/tests/run_agent/test_streaming_tool_call_repair.py index e85c0e22d18..a70c65e47a5 100644 --- a/tests/run_agent/test_streaming_tool_call_repair.py +++ b/tests/run_agent/test_streaming_tool_call_repair.py @@ -12,7 +12,6 @@ unclosed brackets, Python None) don't kill the session. """ import json -import pytest from run_agent import _repair_tool_call_arguments diff --git a/tests/run_agent/test_strict_api_validation.py b/tests/run_agent/test_strict_api_validation.py index a4a53d97db3..16b26b44a94 100644 --- a/tests/run_agent/test_strict_api_validation.py +++ b/tests/run_agent/test_strict_api_validation.py @@ -2,9 +2,7 @@ import sys import types -from unittest.mock import patch, MagicMock -import pytest sys.modules.setdefault("fire", types.SimpleNamespace(Fire=lambda *a, **k: None)) sys.modules.setdefault("firecrawl", types.SimpleNamespace(Firecrawl=object)) diff --git a/tests/run_agent/test_strip_reasoning_tags_cli.py b/tests/run_agent/test_strip_reasoning_tags_cli.py index 7eb15daf43b..0b5c701bc1e 100644 --- a/tests/run_agent/test_strip_reasoning_tags_cli.py +++ b/tests/run_agent/test_strip_reasoning_tags_cli.py @@ -6,7 +6,6 @@ final displayed assistant text (after streaming) without depending on the AIAgent instance. It must stay in sync with run_agent.py::_strip_think_blocks for tool-call tag coverage.""" -import pytest from cli import _strip_reasoning_tags diff --git a/tests/run_agent/test_tls_fd_recycle_corruption.py b/tests/run_agent/test_tls_fd_recycle_corruption.py index 062276db961..29c35612fdf 100644 --- a/tests/run_agent/test_tls_fd_recycle_corruption.py +++ b/tests/run_agent/test_tls_fd_recycle_corruption.py @@ -26,9 +26,8 @@ import logging import socket as _socket import threading from types import SimpleNamespace -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock -import pytest # --------------------------------------------------------------------------- @@ -185,7 +184,6 @@ def test_close_from_stranger_thread_aborts_only_no_close(): the worker's eventual ``finally`` must still see the client in the holder so IT can be the one releasing the FD. """ - from agent.chat_completion_helpers import interruptible_api_call # We can't easily invoke just `_close_request_client_once` because it's # a closure local to ``interruptible_api_call``. Re-extract the same diff --git a/tests/run_agent/test_tool_arg_coercion.py b/tests/run_agent/test_tool_arg_coercion.py index d9ac5dd20fa..e5bbdd93d80 100644 --- a/tests/run_agent/test_tool_arg_coercion.py +++ b/tests/run_agent/test_tool_arg_coercion.py @@ -6,7 +6,6 @@ coerce_tool_args() fixes these type mismatches by comparing argument values against the tool's JSON Schema before dispatch. """ -import pytest from unittest.mock import patch from model_tools import ( diff --git a/tests/run_agent/test_vision_aware_preprocessing.py b/tests/run_agent/test_vision_aware_preprocessing.py index 056754862cc..7a5b6131359 100644 --- a/tests/run_agent/test_vision_aware_preprocessing.py +++ b/tests/run_agent/test_vision_aware_preprocessing.py @@ -15,7 +15,6 @@ from __future__ import annotations from unittest.mock import MagicMock, patch -import pytest from run_agent import AIAgent diff --git a/tests/skills/test_google_workspace_api.py b/tests/skills/test_google_workspace_api.py index 7ecfb4b7b7b..30a1441d634 100644 --- a/tests/skills/test_google_workspace_api.py +++ b/tests/skills/test_google_workspace_api.py @@ -2,7 +2,6 @@ import importlib.util import json -import os import subprocess import sys import types diff --git a/tests/skills/test_google_workspace_credential_files.py b/tests/skills/test_google_workspace_credential_files.py index de59b2fe6e4..9abe3e7e5b2 100644 --- a/tests/skills/test_google_workspace_credential_files.py +++ b/tests/skills/test_google_workspace_credential_files.py @@ -11,7 +11,6 @@ import os from pathlib import Path from unittest.mock import patch -import pytest SKILL_MD = ( Path(__file__).resolve().parents[2] diff --git a/tests/skills/test_memento_cards.py b/tests/skills/test_memento_cards.py index c1e29039c57..6cca138cedd 100644 --- a/tests/skills/test_memento_cards.py +++ b/tests/skills/test_memento_cards.py @@ -2,7 +2,6 @@ import csv import json -import os import sys import uuid from datetime import datetime, timedelta, timezone diff --git a/tests/skills/test_telephony_skill.py b/tests/skills/test_telephony_skill.py index b9025ee5944..0b9483da61c 100644 --- a/tests/skills/test_telephony_skill.py +++ b/tests/skills/test_telephony_skill.py @@ -2,7 +2,6 @@ from __future__ import annotations import importlib.util import json -import os import sys from pathlib import Path diff --git a/tests/skills/test_youtube_quiz.py b/tests/skills/test_youtube_quiz.py index 182889ff6de..810ab71f288 100644 --- a/tests/skills/test_youtube_quiz.py +++ b/tests/skills/test_youtube_quiz.py @@ -3,7 +3,6 @@ import json import sys from pathlib import Path -from types import SimpleNamespace from unittest import mock import pytest diff --git a/tests/stress/_fake_worker.py b/tests/stress/_fake_worker.py index be05bcbedc7..9a4d17bbbbb 100644 --- a/tests/stress/_fake_worker.py +++ b/tests/stress/_fake_worker.py @@ -9,7 +9,6 @@ exactly the way `hermes chat -q` would be, minus the LLM cost. import json import os import subprocess -import sys import time diff --git a/tests/stress/test_atypical_scenarios.py b/tests/stress/test_atypical_scenarios.py index e7e83eabccb..d667a97a7cb 100644 --- a/tests/stress/test_atypical_scenarios.py +++ b/tests/stress/test_atypical_scenarios.py @@ -18,7 +18,6 @@ together at the end. Script exits 0 iff every scenario passed or was cleanly SKIPPED (with reason). """ -import json import multiprocessing as mp import os import shutil diff --git a/tests/stress/test_concurrency.py b/tests/stress/test_concurrency.py index 5cbe455cb02..f5695e4bde1 100644 --- a/tests/stress/test_concurrency.py +++ b/tests/stress/test_concurrency.py @@ -21,7 +21,6 @@ import multiprocessing as mp import os import random import sqlite3 -import subprocess import sys import tempfile import time diff --git a/tests/stress/test_property_fuzzing.py b/tests/stress/test_property_fuzzing.py index b8facc62493..b8270b2b352 100644 --- a/tests/stress/test_property_fuzzing.py +++ b/tests/stress/test_property_fuzzing.py @@ -27,7 +27,6 @@ import os import random import sys import tempfile -import time from pathlib import Path WT = str(Path(__file__).resolve().parents[2]) diff --git a/tests/stress/test_subprocess_e2e.py b/tests/stress/test_subprocess_e2e.py index ea05123000b..ebdab39fd23 100644 --- a/tests/stress/test_subprocess_e2e.py +++ b/tests/stress/test_subprocess_e2e.py @@ -10,7 +10,6 @@ This validates the IPC + lifecycle story that mocks can't: - crash detection works against a real dead PID """ -import json import os from pathlib import Path import subprocess diff --git a/tests/test_batch_runner_checkpoint.py b/tests/test_batch_runner_checkpoint.py index 526c095563d..78bb8c98702 100644 --- a/tests/test_batch_runner_checkpoint.py +++ b/tests/test_batch_runner_checkpoint.py @@ -1,10 +1,8 @@ """Tests for batch_runner checkpoint behavior — incremental writes, resume, atomicity.""" import json -import os from pathlib import Path from threading import Lock -from unittest.mock import patch, MagicMock import pytest diff --git a/tests/test_bitwarden_secrets.py b/tests/test_bitwarden_secrets.py index 3938585469f..dbedd0cb7a5 100644 --- a/tests/test_bitwarden_secrets.py +++ b/tests/test_bitwarden_secrets.py @@ -15,7 +15,6 @@ import os import stat import subprocess import sys -import tempfile import time import zipfile from pathlib import Path diff --git a/tests/test_cli_file_drop.py b/tests/test_cli_file_drop.py index 5161e435f0d..426f2f89c6d 100644 --- a/tests/test_cli_file_drop.py +++ b/tests/test_cli_file_drop.py @@ -1,9 +1,6 @@ """Tests for _detect_file_drop — file path detection that prevents dragged/pasted absolute paths from being mistaken for slash commands.""" -import os -import tempfile -from pathlib import Path import pytest diff --git a/tests/test_ctx_halving_fix.py b/tests/test_ctx_halving_fix.py index bf81ffbae9b..63c965ac965 100644 --- a/tests/test_ctx_halving_fix.py +++ b/tests/test_ctx_halving_fix.py @@ -25,11 +25,10 @@ separate. import sys import os -from unittest.mock import MagicMock, patch, PropertyMock +from unittest.mock import MagicMock sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) -import pytest # --------------------------------------------------------------------------- @@ -307,7 +306,6 @@ class TestContextNotHalvedOnOutputCapError: """On 'max_tokens too large' error, _ephemeral_max_output_tokens is set and compressor.context_length is left unchanged.""" from agent.model_metadata import parse_available_output_tokens_from_error - from agent.model_metadata import get_next_probe_tier error_msg = ( "max_tokens: 128000 > context_window: 200000 " diff --git a/tests/test_empty_model_fallback.py b/tests/test_empty_model_fallback.py index b5f4286727f..32689b325ee 100644 --- a/tests/test_empty_model_fallback.py +++ b/tests/test_empty_model_fallback.py @@ -1,7 +1,6 @@ """Tests for empty model fallback — when provider is configured but model is missing.""" -from unittest.mock import MagicMock, patch -import pytest +from unittest.mock import patch class TestGetDefaultModelForProvider: diff --git a/tests/test_evidence_store.py b/tests/test_evidence_store.py index ff4a0efe243..0bdc16ed163 100644 --- a/tests/test_evidence_store.py +++ b/tests/test_evidence_store.py @@ -1,5 +1,3 @@ -import os -import json import pytest from pathlib import Path import importlib.util diff --git a/tests/test_gateway_streaming_nested_config.py b/tests/test_gateway_streaming_nested_config.py index 8db8988f40c..d69d6b3c601 100644 --- a/tests/test_gateway_streaming_nested_config.py +++ b/tests/test_gateway_streaming_nested_config.py @@ -1,10 +1,7 @@ """Regression test for #25676 — nested gateway.streaming config must be loaded.""" from pathlib import Path from unittest.mock import patch, MagicMock -import json -import pytest -import yaml def _load_with_yaml_dict(yaml_dict: dict): diff --git a/tests/test_hermes_bootstrap.py b/tests/test_hermes_bootstrap.py index a044d644abe..69f3c6b7c03 100644 --- a/tests/test_hermes_bootstrap.py +++ b/tests/test_hermes_bootstrap.py @@ -24,7 +24,6 @@ import os import subprocess import sys import textwrap -import unittest.mock as mock import pytest diff --git a/tests/test_hermes_constants.py b/tests/test_hermes_constants.py index edbb4eb7b84..3bd31c2bf1c 100644 --- a/tests/test_hermes_constants.py +++ b/tests/test_hermes_constants.py @@ -2,7 +2,6 @@ import os from pathlib import Path -from unittest.mock import patch import pytest diff --git a/tests/test_hermes_state.py b/tests/test_hermes_state.py index d0815762175..881856ee0d0 100644 --- a/tests/test_hermes_state.py +++ b/tests/test_hermes_state.py @@ -2,7 +2,6 @@ import time import pytest -from pathlib import Path from hermes_state import SessionDB @@ -2327,7 +2326,6 @@ class TestCompressionChainProjection: Returns (root_id, delegate_id, mid_id, tip_id). """ - import time as _time # Root that gets compressed db.create_session("root1", "cli") db._conn.execute("UPDATE sessions SET started_at=? WHERE id=?", (t0, "root1")) @@ -2642,7 +2640,6 @@ class TestConcurrentWriteSafety: """Connection timeout should be >= 30s to survive CLI/gateway contention.""" # Access the underlying connection timeout via sqlite3 introspection. # There is no public API, so we check the kwarg via the module default. - import sqlite3 import inspect from hermes_state import SessionDB as _SessionDB src = inspect.getsource(_SessionDB.__init__) diff --git a/tests/test_honcho_client_config.py b/tests/test_honcho_client_config.py index feb0eb41d7c..d4c62d610e9 100644 --- a/tests/test_honcho_client_config.py +++ b/tests/test_honcho_client_config.py @@ -2,10 +2,7 @@ import json import os -import tempfile -from pathlib import Path -import pytest from plugins.memory.honcho.client import HonchoClientConfig diff --git a/tests/test_install_sh_symlink_stomp.py b/tests/test_install_sh_symlink_stomp.py index 450d6fe2088..0fbe508509f 100644 --- a/tests/test_install_sh_symlink_stomp.py +++ b/tests/test_install_sh_symlink_stomp.py @@ -20,7 +20,6 @@ import stat import subprocess from pathlib import Path -import pytest REPO_ROOT = Path(__file__).resolve().parent.parent diff --git a/tests/test_ipv4_preference.py b/tests/test_ipv4_preference.py index c57016e2235..c4e5d114782 100644 --- a/tests/test_ipv4_preference.py +++ b/tests/test_ipv4_preference.py @@ -2,9 +2,7 @@ import importlib import socket -from unittest.mock import patch, MagicMock -import pytest def _reload_constants(): diff --git a/tests/test_lazy_session_regressions.py b/tests/test_lazy_session_regressions.py index 511554a4170..0c1ea022064 100644 --- a/tests/test_lazy_session_regressions.py +++ b/tests/test_lazy_session_regressions.py @@ -11,10 +11,8 @@ Tests cover: import threading import time import types -from pathlib import Path from unittest.mock import MagicMock, patch -import pytest # =========================================================================== diff --git a/tests/test_lint_config.py b/tests/test_lint_config.py index 23ca0d6a43a..5d8eda2ae4e 100644 --- a/tests/test_lint_config.py +++ b/tests/test_lint_config.py @@ -82,7 +82,6 @@ class TestLintWorkflow: # Look for the blocking step's named line + its command. We want # at least one ``ruff check .`` that does NOT have ``--exit-zero`` # nearby. - import re # Split into lines and find ruff check invocations lines = content.splitlines() found_blocking = False diff --git a/tests/test_mcp_serve.py b/tests/test_mcp_serve.py index 86e3ae0bd38..11c3b65b609 100644 --- a/tests/test_mcp_serve.py +++ b/tests/test_mcp_serve.py @@ -15,8 +15,7 @@ import os import sqlite3 import time import threading -from pathlib import Path -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock import pytest diff --git a/tests/test_minimax_oauth.py b/tests/test_minimax_oauth.py index f29209cee8c..4b5ca5d54fa 100644 --- a/tests/test_minimax_oauth.py +++ b/tests/test_minimax_oauth.py @@ -15,7 +15,6 @@ import hashlib import json import time from datetime import datetime, timezone -from types import SimpleNamespace from unittest.mock import MagicMock, patch import pytest @@ -26,8 +25,6 @@ from hermes_cli.auth import ( MINIMAX_OAUTH_CLIENT_ID, MINIMAX_OAUTH_GLOBAL_BASE, MINIMAX_OAUTH_GLOBAL_INFERENCE, - MINIMAX_OAUTH_CN_BASE, - MINIMAX_OAUTH_CN_INFERENCE, MINIMAX_OAUTH_REFRESH_SKEW_SECONDS, _minimax_pkce_pair, _minimax_request_user_code, @@ -37,7 +34,6 @@ from hermes_cli.auth import ( resolve_minimax_oauth_runtime_credentials, get_minimax_oauth_auth_status, get_auth_status, - get_provider_auth_state, ) diff --git a/tests/test_model_picker_scroll.py b/tests/test_model_picker_scroll.py index e20c330ea07..f37a82fe611 100644 --- a/tests/test_model_picker_scroll.py +++ b/tests/test_model_picker_scroll.py @@ -14,7 +14,6 @@ isolation without requiring a real TTY. import sys import os -import pytest sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) diff --git a/tests/test_model_tools.py b/tests/test_model_tools.py index beae3daa65e..cb8f9f7a945 100644 --- a/tests/test_model_tools.py +++ b/tests/test_model_tools.py @@ -3,7 +3,6 @@ import json from unittest.mock import ANY, call, patch -import pytest from model_tools import ( handle_function_call, diff --git a/tests/test_model_tools_async_bridge.py b/tests/test_model_tools_async_bridge.py index ed0a85cd355..81ffb2cc624 100644 --- a/tests/test_model_tools_async_bridge.py +++ b/tests/test_model_tools_async_bridge.py @@ -14,7 +14,7 @@ import asyncio import json import threading from types import SimpleNamespace -from unittest.mock import AsyncMock, MagicMock, patch +from unittest.mock import AsyncMock, patch import pytest @@ -129,7 +129,6 @@ class TestRunAsyncWorkerThread: def test_parallel_workers_get_separate_loops(self): """Different worker threads must get their own loops to avoid contention (the original reason for the worker-thread branch).""" - import time from concurrent.futures import ThreadPoolExecutor, as_completed from model_tools import _run_async @@ -356,7 +355,7 @@ class TestVisionDispatchLoopSafety: def test_vision_dispatch_keeps_loop_alive(self, tmp_path): """After dispatching vision_analyze via the registry, the event loop must remain open so cached async clients don't crash on GC.""" - from model_tools import _run_async, _get_tool_loop + from model_tools import _get_tool_loop from tools.registry import registry fake_response = _mock_vision_response() diff --git a/tests/test_ollama_num_ctx.py b/tests/test_ollama_num_ctx.py index fff0144d33b..94b1d7fd6a0 100644 --- a/tests/test_ollama_num_ctx.py +++ b/tests/test_ollama_num_ctx.py @@ -7,7 +7,6 @@ Covers: from unittest.mock import patch, MagicMock -import pytest from agent.model_metadata import query_ollama_num_ctx diff --git a/tests/test_plugin_skills.py b/tests/test_plugin_skills.py index 9764da92b6e..d528b99b5ad 100644 --- a/tests/test_plugin_skills.py +++ b/tests/test_plugin_skills.py @@ -8,9 +8,6 @@ Covers: import json import logging -import os -from pathlib import Path -from unittest.mock import MagicMock import pytest diff --git a/tests/test_process_loop_event_loop_warning.py b/tests/test_process_loop_event_loop_warning.py index 5955544241c..7251060ef85 100644 --- a/tests/test_process_loop_event_loop_warning.py +++ b/tests/test_process_loop_event_loop_warning.py @@ -8,7 +8,6 @@ running loop. """ import asyncio -import sys import threading import warnings diff --git a/tests/test_subprocess_home_isolation.py b/tests/test_subprocess_home_isolation.py index 28401fa6644..4c69c719b6e 100644 --- a/tests/test_subprocess_home_isolation.py +++ b/tests/test_subprocess_home_isolation.py @@ -10,9 +10,7 @@ See: https://github.com/NousResearch/hermes-agent/issues/4426 import os import threading from pathlib import Path -from unittest.mock import patch -import pytest # --------------------------------------------------------------------------- diff --git a/tests/test_timezone.py b/tests/test_timezone.py index f91a27b6a75..b5da11e49fa 100644 --- a/tests/test_timezone.py +++ b/tests/test_timezone.py @@ -14,7 +14,7 @@ import logging import sys import pytest from datetime import datetime, timedelta, timezone -from unittest.mock import patch, MagicMock +from unittest.mock import patch from zoneinfo import ZoneInfo import hermes_time diff --git a/tests/test_toolset_distributions.py b/tests/test_toolset_distributions.py index 6485208be84..9b59946ef21 100644 --- a/tests/test_toolset_distributions.py +++ b/tests/test_toolset_distributions.py @@ -1,7 +1,6 @@ """Tests for toolset_distributions.py — distribution CRUD, sampling, validation.""" import pytest -from unittest.mock import patch from toolset_distributions import ( DISTRIBUTIONS, diff --git a/tests/test_toolsets.py b/tests/test_toolsets.py index a6f4fc6b72e..1773d281af9 100644 --- a/tests/test_toolsets.py +++ b/tests/test_toolsets.py @@ -7,7 +7,6 @@ from toolsets import ( resolve_toolset, resolve_multiple_toolsets, get_all_toolsets, - get_toolset_names, validate_toolset, create_custom_toolset, get_toolset_info, diff --git a/tests/test_trajectory_compressor.py b/tests/test_trajectory_compressor.py index 7978aab4c25..74d63002923 100644 --- a/tests/test_trajectory_compressor.py +++ b/tests/test_trajectory_compressor.py @@ -1,7 +1,6 @@ """Tests for trajectory_compressor.py — config, metrics, and compression logic.""" import importlib -import json import os import sys from types import SimpleNamespace diff --git a/tests/test_trajectory_compressor_async.py b/tests/test_trajectory_compressor_async.py index 369b980b8fb..89c381b5242 100644 --- a/tests/test_trajectory_compressor_async.py +++ b/tests/test_trajectory_compressor_async.py @@ -10,7 +10,6 @@ The fix creates the AsyncOpenAI client lazily via _get_async_client() so each asyncio.run() gets a client bound to the current loop. """ -import types from types import SimpleNamespace from unittest.mock import MagicMock, patch diff --git a/tests/test_transform_tool_result_hook.py b/tests/test_transform_tool_result_hook.py index 508c0bdc0c7..1b414642200 100644 --- a/tests/test_transform_tool_result_hook.py +++ b/tests/test_transform_tool_result_hook.py @@ -5,10 +5,8 @@ Mirrors the ``transform_terminal_output`` hook tests from Phase 1 but targets the generic tool-result seam that runs for every tool dispatch. """ -import json import os from pathlib import Path -from unittest.mock import MagicMock import hermes_cli.plugins as plugins_mod import model_tools diff --git a/tests/test_yuanbao_integration.py b/tests/test_yuanbao_integration.py index 48579c0f886..0b3f0114a73 100644 --- a/tests/test_yuanbao_integration.py +++ b/tests/test_yuanbao_integration.py @@ -20,7 +20,7 @@ if _REPO_ROOT not in sys.path: sys.path.insert(0, _REPO_ROOT) import pytest -from unittest.mock import AsyncMock, MagicMock, patch +from unittest.mock import MagicMock, patch from gateway.config import Platform, PlatformConfig, GatewayConfig from gateway.platforms.yuanbao import YuanbaoAdapter @@ -108,7 +108,6 @@ class TestGatewayRunnerRegistration: def _make_minimal_runner(self, config): """通过 __new__ + 最小初始化绕过 run.py 的模块级 dotenv/ssl 副作用""" import sys - from unittest.mock import MagicMock # Stub out heavy dependencies if not already present stubs = [ @@ -141,7 +140,6 @@ class TestGatewayRunnerRegistration: def test_runner_creates_yuanbao_adapter(self): """GatewayRunner._create_adapter 能为 YUANBAO 返回 YuanbaoAdapter 实例""" from gateway.config import GatewayConfig - from unittest.mock import patch config = make_config(enabled=True) gw_config = GatewayConfig(platforms={Platform.YUANBAO: config}) @@ -159,7 +157,6 @@ class TestGatewayRunnerRegistration: def test_runner_adapter_platform_attr(self): """创建的 adapter.PLATFORM 为 Platform.YUANBAO""" from gateway.config import GatewayConfig - from unittest.mock import patch config = make_config(enabled=True) gw_config = GatewayConfig(platforms={Platform.YUANBAO: config}) diff --git a/tests/test_yuanbao_pipeline.py b/tests/test_yuanbao_pipeline.py index 659f1e70565..c1be92d6802 100644 --- a/tests/test_yuanbao_pipeline.py +++ b/tests/test_yuanbao_pipeline.py @@ -13,7 +13,6 @@ Tests cover: import sys import os import json -import asyncio # Ensure project root is on the path _REPO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) @@ -21,7 +20,7 @@ if _REPO_ROOT not in sys.path: sys.path.insert(0, _REPO_ROOT) import pytest -from unittest.mock import AsyncMock, MagicMock, patch, PropertyMock +from unittest.mock import AsyncMock, MagicMock from gateway.platforms.yuanbao import ( InboundContext, @@ -43,7 +42,7 @@ from gateway.platforms.yuanbao import ( InboundPipelineBuilder, YuanbaoAdapter, ) -from gateway.config import Platform, PlatformConfig +from gateway.config import PlatformConfig # ============================================================ diff --git a/tests/test_yuanbao_proto.py b/tests/test_yuanbao_proto.py index d5dc1fa2fd0..7971a9df8e1 100644 --- a/tests/test_yuanbao_proto.py +++ b/tests/test_yuanbao_proto.py @@ -28,9 +28,6 @@ from gateway.platforms.yuanbao_proto import ( _fields_to_dict, _encode_msg_body_element, _decode_msg_body_element, - _encode_msg_content, - _decode_msg_content, - # conn 层 encode_conn_msg, decode_conn_msg, encode_conn_msg_full, @@ -49,8 +46,6 @@ from gateway.platforms.yuanbao_proto import ( PB_MSG_TYPES, BIZ_SERVICES, CMD_TYPE, - CMD, - MODULE, next_seq_no, ) @@ -434,7 +429,7 @@ class TestEncodeOutbound: def test_c2c_biz_payload_contains_to_account(self): """验证 biz payload 包含 to_account 字段""" - from gateway.platforms.yuanbao_proto import _parse_fields, _fields_to_dict, _get_string + from gateway.platforms.yuanbao_proto import _get_string msg_body = [{"msg_type": "TIMTextElem", "msg_content": {"text": "test"}}] result = encode_send_c2c_message( to_account="target_user", @@ -448,7 +443,7 @@ class TestEncodeOutbound: assert to_acc == "target_user" def test_group_biz_payload_contains_group_code(self): - from gateway.platforms.yuanbao_proto import _parse_fields, _fields_to_dict, _get_string + from gateway.platforms.yuanbao_proto import _get_string msg_body = [{"msg_type": "TIMTextElem", "msg_content": {"text": "test"}}] result = encode_send_group_message( group_code="group-xyz", @@ -595,7 +590,7 @@ class TestEndToEnd: # 从 biz payload 中读取 to_account 和 msg_body from gateway.platforms.yuanbao_proto import ( - _parse_fields, _fields_to_dict, _get_string, _get_repeated_bytes, WT_LEN + _get_string, _get_repeated_bytes ) biz = dec["data"] fdict = _fields_to_dict(_parse_fields(biz)) diff --git a/tests/tools/test_accretion_caps.py b/tests/tools/test_accretion_caps.py index dcd3c09fd97..16be619b2fb 100644 --- a/tests/tools/test_accretion_caps.py +++ b/tests/tools/test_accretion_caps.py @@ -18,7 +18,6 @@ churn accumulated ~20B per session_id until the process exited. These tests pin the new caps + prune hooks. """ -import pytest class TestReadTrackerCaps: diff --git a/tests/tools/test_approval.py b/tests/tools/test_approval.py index 942d27cbe13..3863bc01d06 100644 --- a/tests/tools/test_approval.py +++ b/tests/tools/test_approval.py @@ -17,7 +17,6 @@ from tools.approval import ( is_approved, load_permanent, prompt_dangerous_approval, - submit_pending, ) diff --git a/tests/tools/test_approval_heartbeat.py b/tests/tools/test_approval_heartbeat.py index c725a24eb45..d8531403ec8 100644 --- a/tests/tools/test_approval_heartbeat.py +++ b/tests/tools/test_approval_heartbeat.py @@ -12,9 +12,6 @@ between slices, mirroring ``_wait_for_process`` in ``tools/environments/base.py` """ import os -import threading -import time -from unittest.mock import patch def _clear_approval_state(): diff --git a/tests/tools/test_approval_plugin_hooks.py b/tests/tools/test_approval_plugin_hooks.py index 3b01e620778..58ccb2f8a76 100644 --- a/tests/tools/test_approval_plugin_hooks.py +++ b/tests/tools/test_approval_plugin_hooks.py @@ -13,9 +13,6 @@ import pytest import tools.approval as approval_module from tools.approval import ( check_all_command_guards, - register_gateway_notify, - unregister_gateway_notify, - resolve_gateway_approval, set_current_session_key, clear_session, ) diff --git a/tests/tools/test_base_environment.py b/tests/tools/test_base_environment.py index eb3661cafd3..88fa6a7ea0f 100644 --- a/tests/tools/test_base_environment.py +++ b/tests/tools/test_base_environment.py @@ -4,10 +4,9 @@ Tests _wrap_command(), _extract_cwd_from_output(), _embed_stdin_heredoc(), init_session() failure handling, and the CWD marker contract. """ -import uuid from unittest.mock import MagicMock -from tools.environments.base import BaseEnvironment, _cwd_marker +from tools.environments.base import BaseEnvironment class _TestableEnv(BaseEnvironment): diff --git a/tests/tools/test_browser_camofox.py b/tests/tools/test_browser_camofox.py index cf1c32592f0..3f8ed7fb668 100644 --- a/tests/tools/test_browser_camofox.py +++ b/tests/tools/test_browser_camofox.py @@ -1,10 +1,8 @@ """Tests for the Camofox browser backend.""" import json -import os from unittest.mock import MagicMock, patch -import pytest from tools.browser_camofox import ( camofox_back, diff --git a/tests/tools/test_browser_camofox_state.py b/tests/tools/test_browser_camofox_state.py index f0e632ad5f6..153bb865874 100644 --- a/tests/tools/test_browser_camofox_state.py +++ b/tests/tools/test_browser_camofox_state.py @@ -2,7 +2,6 @@ from unittest.mock import patch -import pytest def _load_module(): diff --git a/tests/tools/test_browser_chromium_check.py b/tests/tools/test_browser_chromium_check.py index 760dfa5d230..33df88735d5 100644 --- a/tests/tools/test_browser_chromium_check.py +++ b/tests/tools/test_browser_chromium_check.py @@ -7,7 +7,6 @@ for the full command timeout before surfacing a useless error. """ import os -from pathlib import Path import pytest diff --git a/tests/tools/test_browser_cloud_fallback.py b/tests/tools/test_browser_cloud_fallback.py index e4f8afd39c9..2759275b61e 100644 --- a/tests/tools/test_browser_cloud_fallback.py +++ b/tests/tools/test_browser_cloud_fallback.py @@ -4,7 +4,7 @@ Covers the fallback logic in _get_session_info() when a cloud provider is configured but fails at runtime (issue #10883). """ import logging -from unittest.mock import Mock, patch +from unittest.mock import Mock import pytest diff --git a/tests/tools/test_browser_console.py b/tests/tools/test_browser_console.py index b058fb3f365..948a213ce1d 100644 --- a/tests/tools/test_browser_console.py +++ b/tests/tools/test_browser_console.py @@ -3,7 +3,6 @@ import json import os import sys -from pathlib import Path from unittest.mock import patch, MagicMock import pytest diff --git a/tests/tools/test_browser_content_none_guard.py b/tests/tools/test_browser_content_none_guard.py index 6952bb938cc..c1e8984822e 100644 --- a/tests/tools/test_browser_content_none_guard.py +++ b/tests/tools/test_browser_content_none_guard.py @@ -9,9 +9,8 @@ These tests verify both sites are guarded. """ import types -from unittest.mock import MagicMock, patch +from unittest.mock import patch -import pytest # ── helpers ──────────────────────────────────────────────────────────────── diff --git a/tests/tools/test_browser_eval_supervisor_path.py b/tests/tools/test_browser_eval_supervisor_path.py index 8528b099489..09a3bcbcaef 100644 --- a/tests/tools/test_browser_eval_supervisor_path.py +++ b/tests/tools/test_browser_eval_supervisor_path.py @@ -8,7 +8,7 @@ real browser, no real WebSocket. Real-CDP coverage lives in from __future__ import annotations import json -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock import pytest diff --git a/tests/tools/test_browser_hardening.py b/tests/tools/test_browser_hardening.py index 374f7af614a..657edad2a20 100644 --- a/tests/tools/test_browser_hardening.py +++ b/tests/tools/test_browser_hardening.py @@ -1,7 +1,6 @@ """Tests for browser_tool.py hardening: caching, security, thread safety, truncation.""" import inspect -import os from unittest.mock import MagicMock, patch import pytest diff --git a/tests/tools/test_browser_homebrew_paths.py b/tests/tools/test_browser_homebrew_paths.py index 7edf6f6c67d..16b7f5607ba 100644 --- a/tests/tools/test_browser_homebrew_paths.py +++ b/tests/tools/test_browser_homebrew_paths.py @@ -2,7 +2,6 @@ import json import os -import subprocess from pathlib import Path from unittest.mock import patch, MagicMock, mock_open diff --git a/tests/tools/test_browser_orphan_reaper.py b/tests/tools/test_browser_orphan_reaper.py index edd8bda6c2d..3f2be1ace00 100644 --- a/tests/tools/test_browser_orphan_reaper.py +++ b/tests/tools/test_browser_orphan_reaper.py @@ -2,10 +2,7 @@ daemons whose Python parent exited without cleaning up.""" import os -import signal -import textwrap -from pathlib import Path -from unittest.mock import patch, MagicMock +from unittest.mock import patch import pytest diff --git a/tests/tools/test_browser_supervisor.py b/tests/tools/test_browser_supervisor.py index 8d844cfefc6..9274145e814 100644 --- a/tests/tools/test_browser_supervisor.py +++ b/tests/tools/test_browser_supervisor.py @@ -17,7 +17,6 @@ from __future__ import annotations import asyncio import base64 import json -import os import shutil import subprocess import tempfile @@ -48,7 +47,6 @@ def chrome_cdp(request): Always launches with ``--site-per-process`` so cross-origin iframes become real OOPIFs (needed by the iframe interaction tests). """ - import socket # xdist worker_id is "master" in single-process mode or "gw0".."gwN" otherwise. # Under subprocess-per-file isolation there's no xdist, so we fall back diff --git a/tests/tools/test_checkpoint_manager.py b/tests/tools/test_checkpoint_manager.py index 84955f224de..5c6db10c011 100644 --- a/tests/tools/test_checkpoint_manager.py +++ b/tests/tools/test_checkpoint_manager.py @@ -23,8 +23,6 @@ from tools.checkpoint_manager import ( _project_meta_path, _touch_project, format_checkpoint_list, - DEFAULT_EXCLUDES, - CHECKPOINT_BASE, prune_checkpoints, maybe_auto_prune_checkpoints, store_status, diff --git a/tests/tools/test_clarify_gateway.py b/tests/tools/test_clarify_gateway.py index 86385be3571..8356d7904ac 100644 --- a/tests/tools/test_clarify_gateway.py +++ b/tests/tools/test_clarify_gateway.py @@ -12,7 +12,6 @@ import threading import time from concurrent.futures import ThreadPoolExecutor -import pytest def _clear_clarify_state(): diff --git a/tests/tools/test_clarify_tool.py b/tests/tools/test_clarify_tool.py index bcdc41929f1..8659e1f13af 100644 --- a/tests/tools/test_clarify_tool.py +++ b/tests/tools/test_clarify_tool.py @@ -3,7 +3,6 @@ import json from typing import List, Optional -import pytest from tools.clarify_tool import ( clarify_tool, diff --git a/tests/tools/test_clipboard.py b/tests/tools/test_clipboard.py index 750874400c4..4a3b31ee56a 100644 --- a/tests/tools/test_clipboard.py +++ b/tests/tools/test_clipboard.py @@ -13,7 +13,7 @@ import queue import subprocess import sys from pathlib import Path -from unittest.mock import patch, MagicMock, PropertyMock, mock_open +from unittest.mock import patch, MagicMock, mock_open import pytest diff --git a/tests/tools/test_code_execution.py b/tests/tools/test_code_execution.py index 2d08265fb7b..bcb46136b7a 100644 --- a/tests/tools/test_code_execution.py +++ b/tests/tools/test_code_execution.py @@ -31,7 +31,6 @@ def _force_local_terminal(monkeypatch): """ monkeypatch.setenv("TERMINAL_ENV", "local") import sys -import time import threading import unittest from unittest.mock import patch, MagicMock diff --git a/tests/tools/test_code_execution_windows_env.py b/tests/tools/test_code_execution_windows_env.py index 70508818fc1..3450288a928 100644 --- a/tests/tools/test_code_execution_windows_env.py +++ b/tests/tools/test_code_execution_windows_env.py @@ -21,16 +21,13 @@ bytes. The child then fails to import with a SyntaxError: """ import os -import socket import subprocess import sys import textwrap -import unittest.mock as mock import pytest from tools.code_execution_tool import ( - _SAFE_ENV_PREFIXES, _SECRET_SUBSTRINGS, _WINDOWS_ESSENTIAL_ENV_VARS, _scrub_child_env, diff --git a/tests/tools/test_command_guards.py b/tests/tools/test_command_guards.py index b9be6837971..fc0d7105aeb 100644 --- a/tests/tools/test_command_guards.py +++ b/tests/tools/test_command_guards.py @@ -10,12 +10,9 @@ from tools.approval import ( approve_session, check_all_command_guards, is_approved, - set_current_session_key, - reset_current_session_key, ) # Ensure the module is importable so we can patch it -import tools.tirith_security # --------------------------------------------------------------------------- diff --git a/tests/tools/test_computer_use.py b/tests/tools/test_computer_use.py index 44a97db47ac..c60a5426f9c 100644 --- a/tests/tools/test_computer_use.py +++ b/tests/tools/test_computer_use.py @@ -5,7 +5,7 @@ from __future__ import annotations import json import os import sys -from typing import Any, Dict, List, Optional, Tuple +from typing import Any, Dict, List from unittest.mock import MagicMock, patch import pytest diff --git a/tests/tools/test_computer_use_capture_routing.py b/tests/tools/test_computer_use_capture_routing.py index 44084fabbea..3eeb983ecea 100644 --- a/tests/tools/test_computer_use_capture_routing.py +++ b/tests/tools/test_computer_use_capture_routing.py @@ -24,8 +24,6 @@ from __future__ import annotations import base64 import json import os -from pathlib import Path -from typing import Any from unittest.mock import MagicMock, patch import pytest diff --git a/tests/tools/test_config_null_guard.py b/tests/tools/test_config_null_guard.py index a6ab64009ce..cb80ab8ecf5 100644 --- a/tests/tools/test_config_null_guard.py +++ b/tests/tools/test_config_null_guard.py @@ -6,7 +6,6 @@ return ``None`` instead of the default — calling ``.lower()`` on that raises """ from unittest.mock import patch -import pytest # ── TTS tool ────────────────────────────────────────────────────────────── diff --git a/tests/tools/test_credential_files.py b/tests/tools/test_credential_files.py index e0ec46a8563..32b4c7664df 100644 --- a/tests/tools/test_credential_files.py +++ b/tests/tools/test_credential_files.py @@ -1,6 +1,5 @@ """Tests for credential file passthrough and skills directory mounting.""" -import json import os from pathlib import Path from unittest.mock import patch diff --git a/tests/tools/test_cron_approval_mode.py b/tests/tools/test_cron_approval_mode.py index 8aae20659a6..007c777e267 100644 --- a/tests/tools/test_cron_approval_mode.py +++ b/tests/tools/test_cron_approval_mode.py @@ -1,6 +1,5 @@ """Tests for approvals.cron_mode — configurable approval behavior for cron jobs.""" -import os import pytest import tools.approval as approval_module diff --git a/tests/tools/test_cronjob_tools.py b/tests/tools/test_cronjob_tools.py index 22d4525af19..18c13b18998 100644 --- a/tests/tools/test_cronjob_tools.py +++ b/tests/tools/test_cronjob_tools.py @@ -2,7 +2,6 @@ import json import pytest -from pathlib import Path from tools.cronjob_tools import ( _scan_cron_prompt, diff --git a/tests/tools/test_cross_profile_guard.py b/tests/tools/test_cross_profile_guard.py index 20814fea1ff..9ea1dd68fd0 100644 --- a/tests/tools/test_cross_profile_guard.py +++ b/tests/tools/test_cross_profile_guard.py @@ -13,7 +13,6 @@ This file tests that the tool surfaces: from __future__ import annotations import json -import os from pathlib import Path import pytest diff --git a/tests/tools/test_daytona_environment.py b/tests/tools/test_daytona_environment.py index 229a4e20e5c..6f50bb7eb37 100644 --- a/tests/tools/test_daytona_environment.py +++ b/tests/tools/test_daytona_environment.py @@ -2,7 +2,7 @@ import threading from types import SimpleNamespace -from unittest.mock import MagicMock, patch, PropertyMock +from unittest.mock import MagicMock import pytest diff --git a/tests/tools/test_delegate.py b/tests/tools/test_delegate.py index 72c4c67f570..3efe21389c5 100644 --- a/tests/tools/test_delegate.py +++ b/tests/tools/test_delegate.py @@ -11,7 +11,6 @@ Run with: python -m pytest tests/test_delegate.py -v import json import os -import sys import threading import time import unittest diff --git a/tests/tools/test_delegate_composite_toolsets.py b/tests/tools/test_delegate_composite_toolsets.py index 85460239949..2c310702f14 100644 --- a/tests/tools/test_delegate_composite_toolsets.py +++ b/tests/tools/test_delegate_composite_toolsets.py @@ -1,7 +1,6 @@ """Tests for composite toolset expansion in delegate_task intersection.""" import unittest -from unittest.mock import patch from tools.delegate_tool import _expand_parent_toolsets diff --git a/tests/tools/test_delegate_subagent_timeout_diagnostic.py b/tests/tools/test_delegate_subagent_timeout_diagnostic.py index 9bb49125a11..ec596f963a6 100644 --- a/tests/tools/test_delegate_subagent_timeout_diagnostic.py +++ b/tests/tools/test_delegate_subagent_timeout_diagnostic.py @@ -16,12 +16,10 @@ These tests pin: """ from __future__ import annotations -import os import threading import time from pathlib import Path -from typing import Optional -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock import pytest diff --git a/tests/tools/test_delegate_toolset_scope.py b/tests/tools/test_delegate_toolset_scope.py index d853dbb042c..175cd8f6485 100644 --- a/tests/tools/test_delegate_toolset_scope.py +++ b/tests/tools/test_delegate_toolset_scope.py @@ -6,7 +6,6 @@ parent's enabled_toolsets, it can escalate privileges by requesting arbitrary toolsets. """ -from unittest.mock import MagicMock, patch from types import SimpleNamespace from tools.delegate_tool import _strip_blocked_tools diff --git a/tests/tools/test_discord_tool.py b/tests/tools/test_discord_tool.py index 7aae982f732..ac94ce5e751 100644 --- a/tests/tools/test_discord_tool.py +++ b/tests/tools/test_discord_tool.py @@ -1,7 +1,6 @@ """Tests for the Discord server introspection and management tool.""" import json -import os import urllib.error from io import BytesIO from unittest.mock import MagicMock, patch @@ -14,7 +13,6 @@ from tools.discord_tool import ( _ADMIN_ACTIONS, _CORE_ACTIONS, _available_actions, - _build_schema, _channel_type_name, _detect_capabilities, _discord_request, diff --git a/tests/tools/test_docker_environment.py b/tests/tools/test_docker_environment.py index 13eb08c9360..688e0f5c85c 100644 --- a/tests/tools/test_docker_environment.py +++ b/tests/tools/test_docker_environment.py @@ -1,8 +1,6 @@ import logging from io import StringIO import subprocess -import sys -import types import pytest diff --git a/tests/tools/test_env_passthrough.py b/tests/tools/test_env_passthrough.py index eba84bdb2cb..974911e588d 100644 --- a/tests/tools/test_env_passthrough.py +++ b/tests/tools/test_env_passthrough.py @@ -198,7 +198,6 @@ class TestTerminalIntegration: def test_make_run_env_blocklist_override_rejected(self): """_make_run_env must NOT expose a blocklisted var to subprocess env even after a skill attempts to register it via passthrough.""" - import os from tools.environments.local import ( _make_run_env, _HERMES_PROVIDER_ENV_BLOCKLIST, diff --git a/tests/tools/test_file_operations.py b/tests/tools/test_file_operations.py index 392e85d8956..f809ea5d912 100644 --- a/tests/tools/test_file_operations.py +++ b/tests/tools/test_file_operations.py @@ -8,8 +8,6 @@ from unittest.mock import MagicMock from tools.file_operations import ( _is_write_denied, - WRITE_DENIED_PATHS, - WRITE_DENIED_PREFIXES, ReadResult, WriteResult, PatchResult, @@ -17,8 +15,6 @@ from tools.file_operations import ( SearchMatch, LintResult, ShellFileOperations, - BINARY_EXTENSIONS, - IMAGE_EXTENSIONS, MAX_LINE_LENGTH, normalize_read_pagination, normalize_search_pagination, diff --git a/tests/tools/test_file_ops_cwd_tracking.py b/tests/tools/test_file_ops_cwd_tracking.py index 3b9e6be4c0a..9df366a6e11 100644 --- a/tests/tools/test_file_ops_cwd_tracking.py +++ b/tests/tools/test_file_ops_cwd_tracking.py @@ -17,10 +17,7 @@ Fix: _exec() now prefers the LIVE ``env.cwd`` over the init-time from __future__ import annotations -import os -import tempfile -import pytest from tools.file_operations import ShellFileOperations diff --git a/tests/tools/test_file_read_guards.py b/tests/tools/test_file_read_guards.py index ca44f6c3eb4..fbe09f360bc 100644 --- a/tests/tools/test_file_read_guards.py +++ b/tests/tools/test_file_read_guards.py @@ -21,7 +21,6 @@ from tools.file_tools import ( _is_blocked_device, _invalidate_dedup_for_path, _READ_DEDUP_STATUS_MESSAGE, - _get_max_read_chars, _DEFAULT_MAX_READ_CHARS, _read_tracker, notify_other_tool_call, diff --git a/tests/tools/test_file_sync_back.py b/tests/tools/test_file_sync_back.py index 9c9da7dc502..a429b3a90da 100644 --- a/tests/tools/test_file_sync_back.py +++ b/tests/tools/test_file_sync_back.py @@ -5,9 +5,8 @@ import logging import os import signal import tarfile -import time from pathlib import Path -from unittest.mock import MagicMock, call, patch +from unittest.mock import MagicMock, patch import pytest diff --git a/tests/tools/test_file_tools.py b/tests/tools/test_file_tools.py index 2ef8411094a..ac28e41ce89 100644 --- a/tests/tools/test_file_tools.py +++ b/tests/tools/test_file_tools.py @@ -9,10 +9,7 @@ import logging from unittest.mock import MagicMock, patch from tools.file_tools import ( - READ_FILE_SCHEMA, - WRITE_FILE_SCHEMA, PATCH_SCHEMA, - SEARCH_FILES_SCHEMA, ) diff --git a/tests/tools/test_file_tools_live.py b/tests/tools/test_file_tools_live.py index 6c3500eb88a..641e7dc6a0a 100644 --- a/tests/tools/test_file_tools_live.py +++ b/tests/tools/test_file_tools_live.py @@ -13,12 +13,10 @@ import pytest -import json import os import sys from pathlib import Path -import pytest sys.path.insert(0, str(Path(__file__).resolve().parents[2])) @@ -388,7 +386,6 @@ class TestExpandPath: # The path should be returned as-is (no expansion). assert result == malicious # Verify the injected command did NOT execute - import os assert not os.path.exists("/tmp/_hermes_injection_test") def test_tilde_username_with_subpath(self, ops): diff --git a/tests/tools/test_hardline_blocklist.py b/tests/tools/test_hardline_blocklist.py index 109badd90fe..8d8062139b8 100644 --- a/tests/tools/test_hardline_blocklist.py +++ b/tests/tools/test_hardline_blocklist.py @@ -6,12 +6,10 @@ gateway /yolo, approvals.mode=off, or cron approve mode. Inspired by Mercury Agent's permission-hardened blocklist. """ -import os import pytest from tools.approval import ( - DANGEROUS_PATTERNS, HARDLINE_PATTERNS, check_all_command_guards, check_dangerous_command, diff --git a/tests/tools/test_heartbeat_stale_thresholds.py b/tests/tools/test_heartbeat_stale_thresholds.py index fb7db68efb9..34a9e59ef20 100644 --- a/tests/tools/test_heartbeat_stale_thresholds.py +++ b/tests/tools/test_heartbeat_stale_thresholds.py @@ -1,6 +1,5 @@ """Tests for delegate heartbeat stale threshold configuration.""" -import pytest class TestHeartbeatStaleThresholds: diff --git a/tests/tools/test_hidden_dir_filter.py b/tests/tools/test_hidden_dir_filter.py index c7757864f74..c72a8fab6bc 100644 --- a/tests/tools/test_hidden_dir_filter.py +++ b/tests/tools/test_hidden_dir_filter.py @@ -7,8 +7,7 @@ This caused quarantined skills (.hub/quarantine/) to appear as installed. Now uses Path.parts which is platform-independent. """ -import os -from pathlib import Path, PurePosixPath, PureWindowsPath +from pathlib import Path def _old_filter_matches(path_str: str) -> bool: diff --git a/tests/tools/test_interrupt.py b/tests/tools/test_interrupt.py index 61a898ac38f..27c61023147 100644 --- a/tests/tools/test_interrupt.py +++ b/tests/tools/test_interrupt.py @@ -65,7 +65,7 @@ class TestPreToolCheck: def test_all_tools_skipped_when_interrupted(self): """Mock an interrupted agent and verify no tools execute.""" - from unittest.mock import MagicMock, patch + from unittest.mock import MagicMock # Build a fake assistant_message with 3 tool calls tc1 = MagicMock() diff --git a/tests/tools/test_kanban_tools.py b/tests/tools/test_kanban_tools.py index 24fa09d8ba2..efc684ba304 100644 --- a/tests/tools/test_kanban_tools.py +++ b/tests/tools/test_kanban_tools.py @@ -9,7 +9,6 @@ Verifies: from __future__ import annotations import json -import os import pytest @@ -26,7 +25,6 @@ def test_kanban_tools_hidden_without_env_var(monkeypatch, tmp_path): home.mkdir() monkeypatch.setenv("HERMES_HOME", str(home)) - import tools.kanban_tools # ensure registered from tools.registry import invalidate_check_fn_cache, registry from toolsets import resolve_toolset @@ -46,7 +44,6 @@ def test_kanban_tools_visible_with_env_var(monkeypatch, tmp_path): home.mkdir() monkeypatch.setenv("HERMES_HOME", str(home)) - import tools.kanban_tools # ensure registered from tools.registry import invalidate_check_fn_cache, registry from toolsets import resolve_toolset @@ -70,7 +67,6 @@ def test_kanban_worker_env_overrides_profile_toolset_filter(monkeypatch, tmp_pat home.mkdir() monkeypatch.setenv("HERMES_HOME", str(home)) - import tools.kanban_tools # ensure registered from model_tools import _clear_tool_defs_cache, get_tool_definitions from tools.registry import invalidate_check_fn_cache @@ -100,7 +96,6 @@ def test_worker_with_kanban_toolset_still_hides_board_routing(monkeypatch, tmp_p (home / "config.yaml").write_text("toolsets:\n - kanban\n") monkeypatch.setenv("HERMES_HOME", str(home)) - import tools.kanban_tools # ensure registered from tools.registry import invalidate_check_fn_cache, registry from toolsets import resolve_toolset @@ -125,7 +120,6 @@ def test_kanban_tools_visible_with_toolset_config(monkeypatch, tmp_path): (home / "config.yaml").write_text("toolsets:\n - kanban\n") monkeypatch.setenv("HERMES_HOME", str(home)) - import tools.kanban_tools # ensure registered from tools.registry import invalidate_check_fn_cache, registry from toolsets import resolve_toolset diff --git a/tests/tools/test_lazy_deps.py b/tests/tools/test_lazy_deps.py index 714c5995eaa..028ef0771e3 100644 --- a/tests/tools/test_lazy_deps.py +++ b/tests/tools/test_lazy_deps.py @@ -12,7 +12,6 @@ call is mocked — we never actually shell out during unit tests. from __future__ import annotations -from typing import Iterator import pytest diff --git a/tests/tools/test_line_ending_preservation.py b/tests/tools/test_line_ending_preservation.py index 82c055cb810..902b41e5fa2 100644 --- a/tests/tools/test_line_ending_preservation.py +++ b/tests/tools/test_line_ending_preservation.py @@ -9,8 +9,6 @@ See issue #507 (Roo Code deep-dive, item 2c). """ import json -import os -import tempfile import pytest diff --git a/tests/tools/test_llm_content_none_guard.py b/tests/tools/test_llm_content_none_guard.py index 5ecdc725d7d..f18101e8273 100644 --- a/tests/tools/test_llm_content_none_guard.py +++ b/tests/tools/test_llm_content_none_guard.py @@ -12,7 +12,6 @@ reasoning fields when content is empty. import asyncio import types -from unittest.mock import AsyncMock, MagicMock, patch import pytest diff --git a/tests/tools/test_local_background_child_hang.py b/tests/tools/test_local_background_child_hang.py index a8cc0ba1024..2ed8c575c69 100644 --- a/tests/tools/test_local_background_child_hang.py +++ b/tests/tools/test_local_background_child_hang.py @@ -10,7 +10,6 @@ of the backgrounded service (indefinitely for a uvicorn server). The fix switches ``_drain()`` to select()-based non-blocking reads and stops draining shortly after bash exits even if the pipe hasn't EOF'd. """ -import json import subprocess import time diff --git a/tests/tools/test_local_env_windows_msys.py b/tests/tools/test_local_env_windows_msys.py index 6987c965af6..529e8b2f2ae 100644 --- a/tests/tools/test_local_env_windows_msys.py +++ b/tests/tools/test_local_env_windows_msys.py @@ -18,10 +18,8 @@ and ``os.path.isdir`` so the MSYS path tests as "missing" exactly like on the real OS. """ -import os from unittest.mock import patch -import pytest from tools.environments import local as local_mod from tools.environments.local import ( diff --git a/tests/tools/test_local_interrupt_cleanup.py b/tests/tools/test_local_interrupt_cleanup.py index 67d9e9e6b54..73b7c76dcb8 100644 --- a/tests/tools/test_local_interrupt_cleanup.py +++ b/tests/tools/test_local_interrupt_cleanup.py @@ -161,7 +161,6 @@ def test_wait_for_process_kills_subprocess_on_keyboardinterrupt(): # way CPython's signal machinery would. We use ctypes.PyThreadState_SetAsyncExc # which is how signal delivery to non-main threads is simulated. import ctypes - import sys as _sys # py-thread-state exception targets need the ident, not the Thread tid = t.ident assert tid is not None diff --git a/tests/tools/test_local_shell_init.py b/tests/tools/test_local_shell_init.py index 7dabaadf12a..1bdaeeeb67a 100644 --- a/tests/tools/test_local_shell_init.py +++ b/tests/tools/test_local_shell_init.py @@ -14,7 +14,6 @@ import pytest from tools.environments.local import ( LocalEnvironment, _prepend_shell_init, - _read_terminal_shell_init_config, _resolve_shell_init_files, ) diff --git a/tests/tools/test_managed_modal_environment.py b/tests/tools/test_managed_modal_environment.py index 8380e49058c..ccf00ca612a 100644 --- a/tests/tools/test_managed_modal_environment.py +++ b/tests/tools/test_managed_modal_environment.py @@ -1,4 +1,3 @@ -import json import sys import tempfile import threading diff --git a/tests/tools/test_mcp_cancelled_error_propagation.py b/tests/tools/test_mcp_cancelled_error_propagation.py index c0e91f31531..13636c3caac 100644 --- a/tests/tools/test_mcp_cancelled_error_propagation.py +++ b/tests/tools/test_mcp_cancelled_error_propagation.py @@ -20,7 +20,6 @@ from __future__ import annotations import asyncio from unittest.mock import patch -import pytest async def _hanging_run(self, cfg): diff --git a/tests/tools/test_mcp_client_cert.py b/tests/tools/test_mcp_client_cert.py index 67663414a23..57ffe8ad723 100644 --- a/tests/tools/test_mcp_client_cert.py +++ b/tests/tools/test_mcp_client_cert.py @@ -15,7 +15,6 @@ Covers: from __future__ import annotations import asyncio -import os from unittest.mock import AsyncMock, MagicMock, patch import pytest diff --git a/tests/tools/test_mcp_empty_error_message.py b/tests/tools/test_mcp_empty_error_message.py index 6c04089f670..b518973085c 100644 --- a/tests/tools/test_mcp_empty_error_message.py +++ b/tests/tools/test_mcp_empty_error_message.py @@ -7,11 +7,7 @@ nothing after the colon, making debugging impossible. Fix: ``_exc_str()`` falls back to ``repr(exc)`` when ``str(exc)`` is empty. """ -import json -from types import SimpleNamespace -from unittest.mock import MagicMock, patch -import pytest from tools.mcp_tool import _exc_str, _sanitize_error diff --git a/tests/tools/test_mcp_image_content.py b/tests/tools/test_mcp_image_content.py index ba60fdfecbd..fecce18f927 100644 --- a/tests/tools/test_mcp_image_content.py +++ b/tests/tools/test_mcp_image_content.py @@ -18,9 +18,7 @@ from __future__ import annotations import base64 from types import SimpleNamespace -from unittest.mock import patch -import pytest def _png_bytes(): diff --git a/tests/tools/test_mcp_oauth.py b/tests/tools/test_mcp_oauth.py index b858127cd07..e43bf0a1851 100644 --- a/tests/tools/test_mcp_oauth.py +++ b/tests/tools/test_mcp_oauth.py @@ -5,8 +5,7 @@ import os import stat import sys from io import BytesIO -from pathlib import Path -from unittest.mock import patch, MagicMock, AsyncMock +from unittest.mock import patch, MagicMock import pytest diff --git a/tests/tools/test_mcp_stability.py b/tests/tools/test_mcp_stability.py index 163a05963e0..1dd76959854 100644 --- a/tests/tools/test_mcp_stability.py +++ b/tests/tools/test_mcp_stability.py @@ -1,12 +1,9 @@ """Tests for MCP stability fixes — event loop handler, PID tracking, shutdown robustness.""" import asyncio -import os import signal -import threading from unittest.mock import patch, MagicMock -import pytest # --------------------------------------------------------------------------- @@ -227,7 +224,7 @@ class TestMCPInitialConnectionRetry: def test_initial_connect_retry_succeeds_on_second_attempt(self): """Server succeeds after one transient initial failure.""" - from tools.mcp_tool import MCPServerTask, _MAX_INITIAL_CONNECT_RETRIES + from tools.mcp_tool import MCPServerTask call_count = 0 diff --git a/tests/tools/test_mcp_tool.py b/tests/tools/test_mcp_tool.py index b9a3cfcf8d9..e2575664748 100644 --- a/tests/tools/test_mcp_tool.py +++ b/tests/tools/test_mcp_tool.py @@ -5,7 +5,6 @@ All tests use mocks -- no real MCP servers or subprocesses are started. import asyncio import json -import os import threading import time from types import SimpleNamespace @@ -1770,7 +1769,7 @@ class TestConfigurableTimeouts: def test_timeout_passed_to_handler(self): """The tool handler uses the server's configured timeout.""" - from tools.mcp_tool import _make_tool_handler, _servers, MCPServerTask + from tools.mcp_tool import _make_tool_handler, _servers mock_session = MagicMock() mock_session.call_tool = AsyncMock( @@ -2225,8 +2224,6 @@ class TestUtilityToolRegistration: # SamplingHandler tests # =========================================================================== -import math -import time class _CompatType: def __init__(self, **kwargs): diff --git a/tests/tools/test_mcp_tool_issue_948.py b/tests/tools/test_mcp_tool_issue_948.py index f7cc00709e4..aefb32481df 100644 --- a/tests/tools/test_mcp_tool_issue_948.py +++ b/tests/tools/test_mcp_tool_issue_948.py @@ -1,10 +1,8 @@ import asyncio import os -import sys from types import SimpleNamespace from unittest.mock import AsyncMock, MagicMock, patch -import pytest from tools.mcp_tool import MCPServerTask, _format_connect_error, _resolve_stdio_command, _MCP_AVAILABLE diff --git a/tests/tools/test_mcp_tool_session_expired.py b/tests/tools/test_mcp_tool_session_expired.py index 59601ba1c3d..b17e6484aab 100644 --- a/tests/tools/test_mcp_tool_session_expired.py +++ b/tests/tools/test_mcp_tool_session_expired.py @@ -12,8 +12,7 @@ affected MCP server failed until the gateway was manually restarted. """ import json import threading -import time -from unittest.mock import AsyncMock, MagicMock +from unittest.mock import MagicMock import pytest diff --git a/tests/tools/test_mcp_utility_capability_gating.py b/tests/tools/test_mcp_utility_capability_gating.py index 971711d75c4..aecee95cc04 100644 --- a/tests/tools/test_mcp_utility_capability_gating.py +++ b/tests/tools/test_mcp_utility_capability_gating.py @@ -29,7 +29,6 @@ from __future__ import annotations from types import SimpleNamespace from unittest.mock import MagicMock -import pytest def _make_init_result(*, resources: bool, prompts: bool): diff --git a/tests/tools/test_memory_tool.py b/tests/tools/test_memory_tool.py index a081e71c690..f23deeff16a 100644 --- a/tests/tools/test_memory_tool.py +++ b/tests/tools/test_memory_tool.py @@ -8,7 +8,6 @@ from tools.memory_tool import ( MemoryStore, memory_tool, _scan_memory_content, - ENTRY_DELIMITER, MEMORY_SCHEMA, ) diff --git a/tests/tools/test_modal_bulk_upload.py b/tests/tools/test_modal_bulk_upload.py index e179e702aa2..4d69a8da594 100644 --- a/tests/tools/test_modal_bulk_upload.py +++ b/tests/tools/test_modal_bulk_upload.py @@ -4,8 +4,7 @@ import asyncio import base64 import io import tarfile -from pathlib import Path -from unittest.mock import AsyncMock, MagicMock, patch +from unittest.mock import AsyncMock, MagicMock import pytest diff --git a/tests/tools/test_notify_on_complete.py b/tests/tools/test_notify_on_complete.py index db086ef6717..84bf5f1f6b5 100644 --- a/tests/tools/test_notify_on_complete.py +++ b/tests/tools/test_notify_on_complete.py @@ -10,11 +10,9 @@ Covers: import json import os -import queue import time import pytest -from pathlib import Path -from unittest.mock import MagicMock, patch +from unittest.mock import patch from tools.process_registry import ( ProcessRegistry, diff --git a/tests/tools/test_process_registry.py b/tests/tools/test_process_registry.py index 10e4421e5f0..b55637135bb 100644 --- a/tests/tools/test_process_registry.py +++ b/tests/tools/test_process_registry.py @@ -7,14 +7,12 @@ import subprocess import sys import time import pytest -from pathlib import Path from unittest.mock import MagicMock, patch from tools.environments.local import _HERMES_PROVIDER_ENV_FORCE_PREFIX from tools.process_registry import ( ProcessRegistry, ProcessSession, - MAX_OUTPUT_CHARS, FINISHED_TTL_SECONDS, MAX_PROCESSES, ) diff --git a/tests/tools/test_resolve_path.py b/tests/tools/test_resolve_path.py index cd4d868961f..4c9cbe30ab6 100644 --- a/tests/tools/test_resolve_path.py +++ b/tests/tools/test_resolve_path.py @@ -4,7 +4,6 @@ import os from pathlib import Path from types import SimpleNamespace -import pytest class TestResolvePath: diff --git a/tests/tools/test_search_hidden_dirs.py b/tests/tools/test_search_hidden_dirs.py index ac963ab1b71..0c214c1583a 100644 --- a/tests/tools/test_search_hidden_dirs.py +++ b/tests/tools/test_search_hidden_dirs.py @@ -13,7 +13,6 @@ Fix: _search_files (find) and _search_with_grep both now exclude hidden directories, matching ripgrep's default behavior. """ -import os import subprocess import pytest diff --git a/tests/tools/test_send_message_tool.py b/tests/tools/test_send_message_tool.py index 1288162587e..3a6ad11fdea 100644 --- a/tests/tools/test_send_message_tool.py +++ b/tests/tools/test_send_message_tool.py @@ -4,7 +4,6 @@ import asyncio import json import os import sys -from pathlib import Path from types import SimpleNamespace from unittest.mock import AsyncMock, MagicMock, patch @@ -40,7 +39,6 @@ from tools.send_message_tool import ( # and provide a thin ``_send_discord(token, ...)`` shim that mirrors the # pre-migration signature so the existing test bodies keep working. from plugins.platforms.discord.adapter import ( - _DISCORD_CHANNEL_TYPE_PROBE_CACHE, _derive_forum_thread_name, _probe_is_forum_cached, _remember_channel_is_forum, @@ -1517,7 +1515,6 @@ class TestSendMatrixUrlEncoding: def test_room_id_is_percent_encoded_in_url(self): """Matrix room IDs with ! and : are percent-encoded in the PUT URL.""" - import aiohttp mock_resp = MagicMock() mock_resp.status = 200 @@ -1894,10 +1891,6 @@ class TestForumProbeCache: discord_adapter._DISCORD_CHANNEL_TYPE_PROBE_CACHE.clear() def test_cache_round_trip(self): - from plugins.platforms.discord.adapter import ( - _probe_is_forum_cached, - _remember_channel_is_forum, - ) assert _probe_is_forum_cached("xyz") is None _remember_channel_is_forum("xyz", True) assert _probe_is_forum_cached("xyz") is True diff --git a/tests/tools/test_signal_media.py b/tests/tools/test_signal_media.py index ee483c08193..6d1bc2112eb 100644 --- a/tests/tools/test_signal_media.py +++ b/tests/tools/test_signal_media.py @@ -2,7 +2,6 @@ import asyncio import sys -from pathlib import Path from types import ModuleType from unittest.mock import MagicMock, AsyncMock, patch diff --git a/tests/tools/test_skill_env_passthrough.py b/tests/tools/test_skill_env_passthrough.py index b4999d83e59..fe15488fa10 100644 --- a/tests/tools/test_skill_env_passthrough.py +++ b/tests/tools/test_skill_env_passthrough.py @@ -1,8 +1,6 @@ """Test that skill_view registers required env vars in the passthrough registry.""" import json -import os -from pathlib import Path from unittest.mock import patch import pytest diff --git a/tests/tools/test_skill_improvements.py b/tests/tools/test_skill_improvements.py index 6e781309f2c..08ca970a469 100644 --- a/tests/tools/test_skill_improvements.py +++ b/tests/tools/test_skill_improvements.py @@ -1,9 +1,6 @@ """Tests for skill fuzzy patching via tools.fuzzy_match.""" import json -import os -from pathlib import Path -from unittest.mock import patch import pytest diff --git a/tests/tools/test_skill_manager_tool.py b/tests/tools/test_skill_manager_tool.py index 33efbb98ae8..e7e5e4a78b2 100644 --- a/tests/tools/test_skill_manager_tool.py +++ b/tests/tools/test_skill_manager_tool.py @@ -12,8 +12,6 @@ from tools.skill_manager_tool import ( _validate_category, _validate_frontmatter, _validate_file_path, - _find_skill, - _resolve_skill_dir, _create_skill, _edit_skill, _patch_skill, @@ -21,8 +19,6 @@ from tools.skill_manager_tool import ( _write_file, _remove_file, skill_manage, - VALID_NAME_RE, - ALLOWED_SUBDIRS, MAX_NAME_LENGTH, ) diff --git a/tests/tools/test_skill_provenance.py b/tests/tools/test_skill_provenance.py index 8cbecc000bc..6c1aedef771 100644 --- a/tests/tools/test_skill_provenance.py +++ b/tests/tools/test_skill_provenance.py @@ -2,7 +2,6 @@ import contextvars -import pytest diff --git a/tests/tools/test_skill_size_limits.py b/tests/tools/test_skill_size_limits.py index c94ba02e81d..6468d6bda30 100644 --- a/tests/tools/test_skill_size_limits.py +++ b/tests/tools/test_skill_size_limits.py @@ -6,15 +6,11 @@ Hand-placed and hub-installed skills have no hard limit. """ import json -import os -from pathlib import Path -from unittest.mock import patch import pytest from tools.skill_manager_tool import ( MAX_SKILL_CONTENT_CHARS, - MAX_SKILL_FILE_BYTES, _validate_content_size, skill_manage, ) diff --git a/tests/tools/test_skill_usage.py b/tests/tools/test_skill_usage.py index 8251e609993..ad306b9c512 100644 --- a/tests/tools/test_skill_usage.py +++ b/tests/tools/test_skill_usage.py @@ -339,7 +339,7 @@ def test_agent_created_skips_archive_and_hub_dirs(skills_home): # --------------------------------------------------------------------------- def test_archive_skill_moves_directory(skills_home): - from tools.skill_usage import archive_skill, get_record, STATE_ARCHIVED + from tools.skill_usage import archive_skill, get_record skills_dir = skills_home / "skills" skill_dir = _write_skill(skills_dir, "old-skill") assert skill_dir.exists() diff --git a/tests/tools/test_skill_view_traversal.py b/tests/tools/test_skill_view_traversal.py index 55d84d8c3f3..426ebb111b7 100644 --- a/tests/tools/test_skill_view_traversal.py +++ b/tests/tools/test_skill_view_traversal.py @@ -6,7 +6,6 @@ reading arbitrary files (e.g., ~/.hermes/.env) via path traversal. import json import pytest -from pathlib import Path from unittest.mock import patch from tools.skills_tool import skill_view diff --git a/tests/tools/test_skills_ast_audit.py b/tests/tools/test_skills_ast_audit.py index c70d6a1f41c..a9de3d57cb9 100644 --- a/tests/tools/test_skills_ast_audit.py +++ b/tests/tools/test_skills_ast_audit.py @@ -1,7 +1,6 @@ """Tests for tools.skills_ast_audit — opt-in AST diagnostic scanner.""" import sys -from pathlib import Path from tools.skills_ast_audit import ast_scan_path, format_ast_report diff --git a/tests/tools/test_skills_guard.py b/tests/tools/test_skills_guard.py index 524da52baa8..b35abdad6e4 100644 --- a/tests/tools/test_skills_guard.py +++ b/tests/tools/test_skills_guard.py @@ -1,7 +1,5 @@ """Tests for tools/skills_guard.py - security scanner for skills.""" -import os -import stat import tempfile from pathlib import Path @@ -33,8 +31,6 @@ from tools.skills_guard import ( _resolve_trust_level, _check_structure, _unicode_char_name, - INSTALL_POLICY, - INVISIBLE_CHARS, MAX_FILE_COUNT, MAX_SINGLE_FILE_KB, ) diff --git a/tests/tools/test_skills_hub.py b/tests/tools/test_skills_hub.py index 85bd4c5e17c..f7b2645e444 100644 --- a/tests/tools/test_skills_hub.py +++ b/tests/tools/test_skills_hub.py @@ -1,7 +1,6 @@ """Tests for tools/skills_hub.py — source adapters, lock file, taps, dedup logic.""" import json -from pathlib import Path from unittest.mock import patch, MagicMock import httpx diff --git a/tests/tools/test_skills_sync.py b/tests/tools/test_skills_sync.py index d0bee8eb78c..1813f4c50e7 100644 --- a/tests/tools/test_skills_sync.py +++ b/tests/tools/test_skills_sync.py @@ -15,8 +15,6 @@ from tools.skills_sync import ( sync_skills, reset_bundled_skill, restore_official_optional_skill, - MANIFEST_FILE, - SKILLS_DIR, ) diff --git a/tests/tools/test_ssh_bulk_upload.py b/tests/tools/test_ssh_bulk_upload.py index afad54cf4f4..a2fa82e6c47 100644 --- a/tests/tools/test_ssh_bulk_upload.py +++ b/tests/tools/test_ssh_bulk_upload.py @@ -2,7 +2,6 @@ import os import subprocess -from pathlib import Path from unittest.mock import MagicMock, patch import pytest diff --git a/tests/tools/test_symlink_prefix_confusion.py b/tests/tools/test_symlink_prefix_confusion.py index c0a7cd7c55f..05a9e281cd1 100644 --- a/tests/tools/test_symlink_prefix_confusion.py +++ b/tests/tools/test_symlink_prefix_confusion.py @@ -6,7 +6,6 @@ for 'axolotl/' because the string prefix matched. Now uses Path.is_relative_to() which handles directory boundaries correctly. """ -import os import pytest from pathlib import Path diff --git a/tests/tools/test_sync_back_backends.py b/tests/tools/test_sync_back_backends.py index 97bec17e28a..0f808512ee7 100644 --- a/tests/tools/test_sync_back_backends.py +++ b/tests/tools/test_sync_back_backends.py @@ -3,7 +3,7 @@ import asyncio import subprocess from pathlib import Path -from unittest.mock import AsyncMock, MagicMock, call, patch +from unittest.mock import AsyncMock, MagicMock, patch import pytest diff --git a/tests/tools/test_terminal_compound_background.py b/tests/tools/test_terminal_compound_background.py index d8922bcf556..eeef435772e 100644 --- a/tests/tools/test_terminal_compound_background.py +++ b/tests/tools/test_terminal_compound_background.py @@ -12,7 +12,6 @@ The rewriter fixes this by wrapping the tail in a brace group — the current shell. No subshell fork, no wait. """ -import pytest from tools.terminal_tool import _rewrite_compound_background as rewrite diff --git a/tests/tools/test_terminal_foreground_timeout_cap.py b/tests/tools/test_terminal_foreground_timeout_cap.py index 54848f62924..0e9893cbad1 100644 --- a/tests/tools/test_terminal_foreground_timeout_cap.py +++ b/tests/tools/test_terminal_foreground_timeout_cap.py @@ -4,7 +4,6 @@ Ensures that foreground commands with timeout > FOREGROUND_MAX_TIMEOUT are rejected with an error suggesting background=true. """ import json -import os from unittest.mock import patch, MagicMock @@ -123,7 +122,7 @@ class TestForegroundTimeoutCap: Only the model's explicit timeout parameter triggers rejection, not the user's configured default. """ - from tools.terminal_tool import terminal_tool, FOREGROUND_MAX_TIMEOUT + from tools.terminal_tool import terminal_tool # User configured TERMINAL_TIMEOUT=900 in their env with patch("tools.terminal_tool._get_env_config", diff --git a/tests/tools/test_terminal_requirements.py b/tests/tools/test_terminal_requirements.py index f06593015ce..a2c1f00e12f 100644 --- a/tests/tools/test_terminal_requirements.py +++ b/tests/tools/test_terminal_requirements.py @@ -1,7 +1,6 @@ import importlib import logging -import pytest terminal_tool_module = importlib.import_module("tools.terminal_tool") diff --git a/tests/tools/test_tirith_security.py b/tests/tools/test_tirith_security.py index cb0556cd93c..4229ae82c6b 100644 --- a/tests/tools/test_tirith_security.py +++ b/tests/tools/test_tirith_security.py @@ -1048,7 +1048,7 @@ class TestDiskFailureMarker: def test_cosign_missing_disk_marker_allows_retry(self): """Disk marker with cosign_missing reason allows retry when cosign appears.""" - from tools.tirith_security import _resolve_tirith_path, _INSTALL_FAILED + from tools.tirith_security import _resolve_tirith_path _tirith_mod._resolved_path = None # _is_install_failed_on_disk sees "cosign_missing" + cosign on PATH → returns False diff --git a/tests/tools/test_tool_result_storage.py b/tests/tools/test_tool_result_storage.py index 17b6815c1d1..0d80581dc2a 100644 --- a/tests/tools/test_tool_result_storage.py +++ b/tests/tools/test_tool_result_storage.py @@ -5,7 +5,6 @@ from unittest.mock import MagicMock, patch from tools.budget_config import ( DEFAULT_RESULT_SIZE_CHARS, - DEFAULT_TURN_BUDGET_CHARS, DEFAULT_PREVIEW_SIZE_CHARS, BudgetConfig, ) diff --git a/tests/tools/test_transcription.py b/tests/tools/test_transcription.py index b7e399ca426..84f6c9679af 100644 --- a/tests/tools/test_transcription.py +++ b/tests/tools/test_transcription.py @@ -4,12 +4,10 @@ Tests cover provider selection, config loading, validation, and transcription dispatch. All external dependencies (faster_whisper, openai) are mocked. """ -import json import os import tempfile -from pathlib import Path from types import SimpleNamespace -from unittest.mock import MagicMock, patch, mock_open +from unittest.mock import MagicMock, patch import pytest @@ -109,7 +107,6 @@ class TestValidateAudioFile: assert _validate_audio_file(str(f)) is None def test_too_large(self, tmp_path): - import stat as stat_mod f = tmp_path / "big.ogg" f.write_bytes(b"x") from tools.transcription_tools import _validate_audio_file, MAX_FILE_SIZE @@ -292,7 +289,7 @@ class TestNormalizeLocalModel: def test_local_transcribe_normalises_model(self): """transcribe_audio with local provider must not pass 'whisper-1' to WhisperModel.""" - import tempfile, os + import os from unittest.mock import MagicMock, patch with tempfile.NamedTemporaryFile(suffix=".ogg", delete=False) as f: diff --git a/tests/tools/test_transcription_command_providers.py b/tests/tools/test_transcription_command_providers.py index 6873b0389ea..749ab5e839c 100644 --- a/tests/tools/test_transcription_command_providers.py +++ b/tests/tools/test_transcription_command_providers.py @@ -19,15 +19,11 @@ identically on Linux, macOS, and Windows (with minor quoting differences). from __future__ import annotations import os -import subprocess import sys -import tempfile import wave from pathlib import Path -from typing import Optional from unittest.mock import patch -import pytest from tools.transcription_tools import ( BUILTIN_STT_PROVIDERS, @@ -39,12 +35,9 @@ from tools.transcription_tools import ( _get_command_stt_timeout, _get_named_stt_provider_config, _has_any_command_stt_provider, - _is_command_stt_provider_config, _iter_command_stt_providers, - _quote_command_stt_placeholder, _render_command_stt_template, _resolve_command_stt_provider_config, - _shell_quote_context_stt, _transcribe_command_stt, transcribe_audio, ) diff --git a/tests/tools/test_tts_command_providers.py b/tests/tools/test_tts_command_providers.py index 583abcb588b..e3242274a00 100644 --- a/tests/tools/test_tts_command_providers.py +++ b/tests/tools/test_tts_command_providers.py @@ -14,10 +14,8 @@ differences) Windows. import json import os -import subprocess import sys from pathlib import Path -from typing import Optional from unittest.mock import patch import pytest diff --git a/tests/tools/test_tts_max_text_length.py b/tests/tools/test_tts_max_text_length.py index 38a763ea78c..49ae5ca2f4b 100644 --- a/tests/tools/test_tts_max_text_length.py +++ b/tests/tools/test_tts_max_text_length.py @@ -6,12 +6,9 @@ MiniMax allows 10000, and ElevenLabs allows 5000-40000 depending on model. """ import json -from unittest.mock import patch -import pytest from tools.tts_tool import ( - ELEVENLABS_MODEL_MAX_TEXT_LENGTH, FALLBACK_MAX_TEXT_LENGTH, PROVIDER_MAX_TEXT_LENGTH, _resolve_max_text_length, diff --git a/tests/tools/test_tts_piper.py b/tests/tools/test_tts_piper.py index ef7330a18c9..c30b26dc9b9 100644 --- a/tests/tools/test_tts_piper.py +++ b/tests/tools/test_tts_piper.py @@ -7,7 +7,6 @@ without requiring the ``piper-tts`` package to actually be installed """ import json -import os import sys from pathlib import Path from unittest.mock import MagicMock, patch diff --git a/tests/tools/test_video_analyze.py b/tests/tools/test_video_analyze.py index 62987d96b20..1294ab8f558 100644 --- a/tests/tools/test_video_analyze.py +++ b/tests/tools/test_video_analyze.py @@ -2,20 +2,14 @@ import asyncio import json -import os -from pathlib import Path -from typing import Awaitable from unittest.mock import AsyncMock, MagicMock, patch -import pytest from tools.vision_tools import ( _detect_video_mime_type, _video_to_base64_data_url, _handle_video_analyze, _MAX_VIDEO_BASE64_BYTES, - _VIDEO_MIME_TYPES, - _VIDEO_SIZE_WARN_BYTES, video_analyze_tool, VIDEO_ANALYZE_SCHEMA, ) diff --git a/tests/tools/test_video_generation_tool_surface_matrix.py b/tests/tools/test_video_generation_tool_surface_matrix.py index 3dc3257fc58..e15245686d9 100644 --- a/tests/tools/test_video_generation_tool_surface_matrix.py +++ b/tests/tools/test_video_generation_tool_surface_matrix.py @@ -16,7 +16,7 @@ from __future__ import annotations import asyncio import json import types -from typing import Any, Dict, List, Optional +from typing import Any, Dict, List import pytest import yaml diff --git a/tests/tools/test_vision_native_fast_path.py b/tests/tools/test_vision_native_fast_path.py index 1df3003e5cd..89b9724e254 100644 --- a/tests/tools/test_vision_native_fast_path.py +++ b/tests/tools/test_vision_native_fast_path.py @@ -11,10 +11,8 @@ from __future__ import annotations import asyncio import base64 import json -from pathlib import Path from unittest.mock import patch -import pytest from tools.vision_tools import ( _build_native_vision_tool_result, diff --git a/tests/tools/test_vision_tools.py b/tests/tools/test_vision_tools.py index d8977f84927..e3bff50d56f 100644 --- a/tests/tools/test_vision_tools.py +++ b/tests/tools/test_vision_tools.py @@ -1,6 +1,5 @@ """Tests for tools/vision_tools.py — URL validation, type hints, error logging.""" -import asyncio import json import logging import os diff --git a/tests/tools/test_voice_cli_integration.py b/tests/tools/test_voice_cli_integration.py index babdb4e7383..f43eb97c96d 100644 --- a/tests/tools/test_voice_cli_integration.py +++ b/tests/tools/test_voice_cli_integration.py @@ -2,7 +2,6 @@ state management, streaming TTS activation, voice message prefix, _vprint.""" import ast -import os import queue import threading from types import SimpleNamespace diff --git a/tests/tools/test_voice_mode.py b/tests/tools/test_voice_mode.py index fdab4e8d8eb..2a2b77bae2e 100644 --- a/tests/tools/test_voice_mode.py +++ b/tests/tools/test_voice_mode.py @@ -944,7 +944,7 @@ class TestSilenceDetection: mock_stream = MagicMock() mock_sd.InputStream.return_value = mock_stream - from tools.voice_mode import AudioRecorder, SAMPLE_RATE + from tools.voice_mode import AudioRecorder recorder = AudioRecorder() # Use very short durations for testing @@ -1322,7 +1322,7 @@ class TestSubprocessTimeoutKill: """Bug: proc.wait(timeout) raised TimeoutExpired but process was not killed.""" def test_timeout_kills_process(self): - import subprocess, os + import subprocess proc = subprocess.Popen(["sleep", "600"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) pid = proc.pid assert proc.poll() is None diff --git a/tests/tools/test_watch_patterns.py b/tests/tools/test_watch_patterns.py index b2d8677b362..3d64acd0657 100644 --- a/tests/tools/test_watch_patterns.py +++ b/tests/tools/test_watch_patterns.py @@ -11,7 +11,6 @@ Covers: """ import json -import queue import time import pytest from unittest.mock import patch @@ -19,11 +18,8 @@ from unittest.mock import patch from tools.process_registry import ( ProcessRegistry, ProcessSession, - WATCH_MIN_INTERVAL_SECONDS, WATCH_STRIKE_LIMIT, WATCH_GLOBAL_MAX_PER_WINDOW, - WATCH_GLOBAL_WINDOW_SECONDS, - WATCH_GLOBAL_COOLDOWN_SECONDS, ) diff --git a/tests/tools/test_web_providers.py b/tests/tools/test_web_providers.py index b8f175a68f2..5dd65199ec8 100644 --- a/tests/tools/test_web_providers.py +++ b/tests/tools/test_web_providers.py @@ -295,7 +295,6 @@ class TestUnconfiguredErrorEnvelopeParity: """``web_search_tool`` with no creds returns ``{"error": "Error searching web: ..."}`` — matching main's ``tool_error()`` envelope, not a per-result shape. """ - import json from tools import web_tools self._clear_web_creds(monkeypatch) diff --git a/tests/tools/test_web_providers_ddgs.py b/tests/tools/test_web_providers_ddgs.py index a2fdb1e1e76..7919931614f 100644 --- a/tests/tools/test_web_providers_ddgs.py +++ b/tests/tools/test_web_providers_ddgs.py @@ -12,7 +12,6 @@ from __future__ import annotations import json import sys import types -from unittest.mock import MagicMock import pytest diff --git a/tests/tools/test_web_providers_searxng.py b/tests/tools/test_web_providers_searxng.py index d237e682973..31bbaeb47ca 100644 --- a/tests/tools/test_web_providers_searxng.py +++ b/tests/tools/test_web_providers_searxng.py @@ -12,7 +12,6 @@ Covers: from __future__ import annotations import json -import os from unittest.mock import MagicMock, patch import pytest @@ -322,7 +321,6 @@ class TestSearXNGOnlyExtractCrawlErrors: monkeypatch.setattr(web_tools, "is_safe_url", lambda url: True) monkeypatch.setattr("tools.interrupt.is_interrupted", lambda: False, raising=False) - import json result_str = asyncio.get_event_loop().run_until_complete( web_tools.web_extract_tool(["https://example.com"]) ) diff --git a/tests/tools/test_website_policy.py b/tests/tools/test_website_policy.py index 37257ad4017..bfe222ef892 100644 --- a/tests/tools/test_website_policy.py +++ b/tests/tools/test_website_policy.py @@ -326,7 +326,6 @@ def test_browser_navigate_returns_policy_block(monkeypatch): def test_browser_navigate_allows_when_shared_file_missing(monkeypatch, tmp_path): """Missing shared blocklist files are warned and skipped, not fatal.""" - from tools import browser_tool config_path = tmp_path / "config.yaml" config_path.write_text( diff --git a/tests/tools/test_windows_native_support.py b/tests/tools/test_windows_native_support.py index f92ed22dff7..baba1985950 100644 --- a/tests/tools/test_windows_native_support.py +++ b/tests/tools/test_windows_native_support.py @@ -11,13 +11,11 @@ Windows runner. from __future__ import annotations -import importlib import os import signal -import subprocess import sys from pathlib import Path -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock import pytest diff --git a/tests/tools/test_write_deny.py b/tests/tools/test_write_deny.py index 02fca0eca13..6fe6c802ace 100644 --- a/tests/tools/test_write_deny.py +++ b/tests/tools/test_write_deny.py @@ -2,7 +2,6 @@ import os -import pytest from pathlib import Path from unittest.mock import patch diff --git a/tests/tools/test_zombie_process_cleanup.py b/tests/tools/test_zombie_process_cleanup.py index 8085d112318..e31e042fb20 100644 --- a/tests/tools/test_zombie_process_cleanup.py +++ b/tests/tools/test_zombie_process_cleanup.py @@ -9,10 +9,8 @@ import os import signal import subprocess import sys -import time import threading -import pytest def _spawn_sleep(seconds: float = 60) -> subprocess.Popen: @@ -191,7 +189,7 @@ class TestGatewayCleanupWiring: """gateway stop() should call close() on all running agents.""" import asyncio import threading - from unittest.mock import AsyncMock, MagicMock, patch + from unittest.mock import MagicMock, patch from gateway.run import GatewayRunner diff --git a/tests/tui_gateway/test_entry_sys_path.py b/tests/tui_gateway/test_entry_sys_path.py index e7f9e47cee0..15619d2a9fc 100644 --- a/tests/tui_gateway/test_entry_sys_path.py +++ b/tests/tui_gateway/test_entry_sys_path.py @@ -6,7 +6,6 @@ to shadow the installed utils module. entry.py must sanitize sys.path before any non-stdlib import is resolved. """ -import importlib import os import sys from unittest.mock import patch diff --git a/tests/tui_gateway/test_review_summary_callback.py b/tests/tui_gateway/test_review_summary_callback.py index f2d97f1a487..56ca2d4944f 100644 --- a/tests/tui_gateway/test_review_summary_callback.py +++ b/tests/tui_gateway/test_review_summary_callback.py @@ -11,7 +11,6 @@ transcript line. from __future__ import annotations -import sys from unittest.mock import MagicMock, patch import pytest diff --git a/tools/browser_cdp_tool.py b/tools/browser_cdp_tool.py index e2aae88308f..e13264767d9 100644 --- a/tools/browser_cdp_tool.py +++ b/tools/browser_cdp_tool.py @@ -257,7 +257,6 @@ def _browser_cdp_via_supervisor( ) # Dispatch onto the supervisor's loop. - import asyncio as _asyncio loop = supervisor._loop # type: ignore[attr-defined] if loop is None or not loop.is_running(): return tool_error( diff --git a/tools/browser_tool.py b/tools/browser_tool.py index 5320d6adfdb..926e6c3e552 100644 --- a/tools/browser_tool.py +++ b/tools/browser_tool.py @@ -55,7 +55,6 @@ import json import logging import os import re -import signal import subprocess import shutil import sys diff --git a/tools/code_execution_tool.py b/tools/code_execution_tool.py index 19aee58c8db..23c0434b660 100644 --- a/tools/code_execution_tool.py +++ b/tools/code_execution_tool.py @@ -35,7 +35,6 @@ import logging import os import platform import shlex -import signal import socket import subprocess import sys diff --git a/tools/computer_use/cua_backend.py b/tools/computer_use/cua_backend.py index ffdeeb2a388..cb449b063f3 100644 --- a/tools/computer_use/cua_backend.py +++ b/tools/computer_use/cua_backend.py @@ -25,10 +25,8 @@ import os import platform import re import shutil -import subprocess import sys import threading -from concurrent.futures import Future from typing import Any, Dict, List, Optional, Tuple from tools.computer_use.backend import ( diff --git a/tools/cronjob_tools.py b/tools/cronjob_tools.py index 18c68a7ce91..ada4e4af006 100644 --- a/tools/cronjob_tools.py +++ b/tools/cronjob_tools.py @@ -7,7 +7,6 @@ Compatibility wrappers remain for direct Python callers and legacy tests. import json import logging -import os import re import sys from pathlib import Path @@ -23,7 +22,6 @@ sys.path.insert(0, str(Path(__file__).parent.parent)) from cron.jobs import ( AmbiguousJobReference, create_job, - get_job, list_jobs, parse_schedule, pause_job, diff --git a/tools/environments/local.py b/tools/environments/local.py index 81d470f9b63..7e9e7c1840e 100644 --- a/tools/environments/local.py +++ b/tools/environments/local.py @@ -316,7 +316,7 @@ def _make_run_env(env: dict) -> dict: # Inject ContextVar-based session vars into subprocess env. # ContextVars don't propagate to child processes, so we bridge them here. try: - from gateway.session_context import get_session_env, _UNSET, _VAR_MAP + from gateway.session_context import _UNSET, _VAR_MAP for var_name, var in _VAR_MAP.items(): value = var.get() if value is not _UNSET and value: diff --git a/tools/memory_tool.py b/tools/memory_tool.py index 5b9af55928e..281c806ea09 100644 --- a/tools/memory_tool.py +++ b/tools/memory_tool.py @@ -26,7 +26,6 @@ Design: import json import logging import os -import re import tempfile import time from contextlib import contextmanager diff --git a/tools/send_message_tool.py b/tools/send_message_tool.py index dab83b854ed..9ea0b9af41b 100644 --- a/tools/send_message_tool.py +++ b/tools/send_message_tool.py @@ -13,7 +13,6 @@ import re import ssl import time from email.utils import formatdate -from typing import Dict, Optional from agent.redact import redact_sensitive_text @@ -1270,7 +1269,6 @@ async def _send_email(extra, chat_id, message): """Send via SMTP (one-shot, no persistent connection needed).""" import smtplib from email.mime.text import MIMEText - from email.utils import formatdate address = extra.get("address") or os.getenv("EMAIL_ADDRESS", "") password = os.getenv("EMAIL_PASSWORD", "") diff --git a/tools/skill_usage.py b/tools/skill_usage.py index 52a6d74dbac..745b68ead8c 100644 --- a/tools/skill_usage.py +++ b/tools/skill_usage.py @@ -31,7 +31,7 @@ import tempfile from contextlib import contextmanager from datetime import datetime, timezone from pathlib import Path -from typing import Any, Dict, Iterable, List, Optional, Set, Tuple +from typing import Any, Dict, List, Optional, Set, Tuple from hermes_constants import get_hermes_home from agent.skill_utils import is_excluded_skill_path diff --git a/tools/web_tools.py b/tools/web_tools.py index cfe722c2ba7..33dbd39c9e6 100644 --- a/tools/web_tools.py +++ b/tools/web_tools.py @@ -51,21 +51,9 @@ import httpx # noqa: F401 — kept at module top so tests can patch tools.web_t if TYPE_CHECKING: from firecrawl import Firecrawl # noqa: F401 — type hints only from plugins.web.firecrawl.provider import ( - Firecrawl, - _FirecrawlProxy, - _FIRECRAWL_CLS_CACHE, - _extract_scrape_payload, - _extract_web_search_results, _firecrawl_backend_help_suffix, - _get_direct_firecrawl_config, - _get_firecrawl_client, _get_firecrawl_gateway_url, - _has_direct_firecrawl_config, _is_tool_gateway_ready, - _load_firecrawl_cls, - _normalize_result_list, - _raise_web_backend_configuration_error, - _to_plain_object, check_firecrawl_api_key, ) # Tavily helpers re-exported for backward-compat with existing unit tests @@ -112,7 +100,6 @@ from tools.tool_backend_helpers import ( # noqa: F401 prefers_gateway, ) from tools.url_safety import is_safe_url -from tools.website_policy import check_website_access import sys logger = logging.getLogger(__name__) diff --git a/tools/x_search_tool.py b/tools/x_search_tool.py index 70251860736..39ecf2daf33 100644 --- a/tools/x_search_tool.py +++ b/tools/x_search_tool.py @@ -44,7 +44,6 @@ from __future__ import annotations import json import logging -import os import time from datetime import date, datetime, timezone from typing import Any, Dict, List, Optional, Tuple diff --git a/tui_gateway/server.py b/tui_gateway/server.py index 47e502a001b..77d1ea502eb 100644 --- a/tui_gateway/server.py +++ b/tui_gateway/server.py @@ -3128,7 +3128,6 @@ def _(rid, params: dict) -> dict: def _spawn_trees_root(): - from pathlib import Path as _P from hermes_constants import get_hermes_home root = get_hermes_home() / "spawn-trees" diff --git a/website/scripts/generate-skill-docs.py b/website/scripts/generate-skill-docs.py index c932f01e1bc..2d2b19b1997 100755 --- a/website/scripts/generate-skill-docs.py +++ b/website/scripts/generate-skill-docs.py @@ -14,10 +14,8 @@ Sidebar is updated to nest all per-skill pages under Skills → Bundled / Option from __future__ import annotations import re -import sys from collections import defaultdict from pathlib import Path -from textwrap import dedent from typing import Any import yaml