chore: remove ~100 unused imports across 55 files (#3016)

Automated cleanup via pyflakes + autoflake with manual review.

Changes:
- Removed unused stdlib imports (os, sys, json, pathlib.Path, etc.)
- Removed unused typing imports (List, Dict, Any, Optional, Tuple, Set, etc.)
- Removed unused internal imports (hermes_cli.auth, hermes_cli.config, etc.)
- Fixed cli.py: removed 8 shadowed banner imports (imported from hermes_cli.banner
  then immediately redefined locally — only build_welcome_banner is actually used)
- Added noqa comments to imports that appear unused but serve a purpose:
  - Re-exports (gateway/session.py SessionResetPolicy, tools/terminal_tool.py
    is_interrupted/_interrupt_event)
  - SDK presence checks in try/except (daytona, fal_client, discord)
  - Test mock targets (auxiliary_client.py Path, mcp_config.py get_hermes_home)

Zero behavioral changes. Full test suite passes (6162/6162, 2 pre-existing
streaming test failures unrelated to this change).
This commit is contained in:
Teknium 2026-03-25 15:02:03 -07:00 committed by GitHub
parent 861624d4e9
commit 8bb1d15da4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
55 changed files with 51 additions and 119 deletions

View file

@ -10,7 +10,7 @@ thread while the event loop lives on the main thread).
import asyncio import asyncio
import json import json
import logging import logging
from collections import defaultdict, deque from collections import deque
from typing import Any, Callable, Deque, Dict from typing import Any, Callable, Deque, Dict
import acp import acp

View file

@ -5,14 +5,11 @@ from __future__ import annotations
import asyncio import asyncio
import logging import logging
from concurrent.futures import TimeoutError as FutureTimeout from concurrent.futures import TimeoutError as FutureTimeout
from typing import Any, Callable, Optional from typing import Callable
from acp.schema import ( from acp.schema import (
AllowedOutcome, AllowedOutcome,
DeniedOutcome,
PermissionOption, PermissionOption,
RequestPermissionRequest,
SelectedPermissionOutcome,
) )
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View file

@ -41,7 +41,7 @@ import logging
import os import os
import threading import threading
import time import time
from pathlib import Path from pathlib import Path # noqa: F401 — used by test mocks
from types import SimpleNamespace from types import SimpleNamespace
from typing import Any, Dict, List, Optional, Tuple from typing import Any, Dict, List, Optional, Tuple

View file

@ -14,7 +14,6 @@ Improvements over v1:
""" """
import logging import logging
import os
from typing import Any, Dict, List, Optional from typing import Any, Dict, List, Optional
from agent.auxiliary_client import call_llm from agent.auxiliary_client import call_llm

20
cli.py
View file

@ -458,13 +458,8 @@ from run_agent import AIAgent
from model_tools import get_tool_definitions, get_toolset_for_tool from model_tools import get_tool_definitions, get_toolset_for_tool
# Extracted CLI modules (Phase 3) # Extracted CLI modules (Phase 3)
from hermes_cli.banner import ( from hermes_cli.banner import build_welcome_banner
cprint as _cprint, _GOLD, _BOLD, _DIM, _RST, from hermes_cli.commands import SlashCommandCompleter, SlashCommandAutoSuggest
HERMES_AGENT_LOGO, HERMES_CADUCEUS, COMPACT_BANNER,
build_welcome_banner,
)
from hermes_cli.commands import COMMANDS, SlashCommandCompleter, SlashCommandAutoSuggest
from hermes_cli import callbacks as _callbacks
from toolsets import get_all_toolsets, get_toolset_info, validate_toolset from toolsets import get_all_toolsets, get_toolset_info, validate_toolset
# Cron job system for scheduled tasks (execution is handled by the gateway) # Cron job system for scheduled tasks (execution is handled by the gateway)
@ -2341,7 +2336,7 @@ class HermesCLI:
/rollback diff <N> preview changes since checkpoint N /rollback diff <N> preview changes since checkpoint N
/rollback <N> <file> restore a single file from checkpoint N /rollback <N> <file> restore a single file from checkpoint N
""" """
from tools.checkpoint_manager import CheckpointManager, format_checkpoint_list from tools.checkpoint_manager import format_checkpoint_list
if not hasattr(self, 'agent') or not self.agent: if not hasattr(self, 'agent') or not self.agent:
print(" No active agent session.") print(" No active agent session.")
@ -2541,7 +2536,7 @@ class HermesCLI:
def _show_tool_availability_warnings(self): def _show_tool_availability_warnings(self):
"""Show warnings about disabled tools due to missing API keys.""" """Show warnings about disabled tools due to missing API keys."""
try: try:
from model_tools import check_tool_availability, TOOLSET_REQUIREMENTS from model_tools import check_tool_availability
available, unavailable = check_tool_availability() available, unavailable = check_tool_availability()
@ -4134,7 +4129,6 @@ class HermesCLI:
def _handle_browser_command(self, cmd: str): def _handle_browser_command(self, cmd: str):
"""Handle /browser connect|disconnect|status — manage live Chrome CDP connection.""" """Handle /browser connect|disconnect|status — manage live Chrome CDP connection."""
import platform as _plat import platform as _plat
import subprocess as _sp
parts = cmd.strip().split(None, 1) parts = cmd.strip().split(None, 1)
sub = parts[1].lower().strip() if len(parts) > 1 else "status" sub = parts[1].lower().strip() if len(parts) > 1 else "status"
@ -4636,7 +4630,7 @@ class HermesCLI:
sees the updated tools on the next turn. sees the updated tools on the next turn.
""" """
try: try:
from tools.mcp_tool import shutdown_mcp_servers, discover_mcp_tools, _load_mcp_config, _servers, _lock from tools.mcp_tool import shutdown_mcp_servers, discover_mcp_tools, _servers, _lock
# Capture old server names # Capture old server names
with _lock: with _lock:
@ -4956,7 +4950,6 @@ class HermesCLI:
try: try:
from tools.tts_tool import text_to_speech_tool from tools.tts_tool import text_to_speech_tool
from tools.voice_mode import play_audio_file from tools.voice_mode import play_audio_file
import json
import re import re
# Strip markdown and non-speech content for cleaner TTS # Strip markdown and non-speech content for cleaner TTS
@ -6530,8 +6523,7 @@ class HermesCLI:
"""Return provider/model info for /model autocomplete.""" """Return provider/model info for /model autocomplete."""
try: try:
from hermes_cli.models import ( from hermes_cli.models import (
_PROVIDER_LABELS, _PROVIDER_MODELS, normalize_provider, _PROVIDER_LABELS, normalize_provider, provider_model_ids,
provider_model_ids,
) )
current = getattr(cli_ref, "provider", None) or getattr(cli_ref, "requested_provider", "openrouter") current = getattr(cli_ref, "provider", None) or getattr(cli_ref, "requested_provider", "openrouter")
current = normalize_provider(current) current = normalize_provider(current)

View file

@ -24,7 +24,6 @@ except ImportError:
import msvcrt import msvcrt
except ImportError: except ImportError:
msvcrt = None msvcrt = None
from datetime import datetime
from pathlib import Path from pathlib import Path
from typing import Optional from typing import Optional

View file

@ -9,7 +9,6 @@ action="list" and for resolving human-friendly channel names to numeric IDs.
import json import json
import logging import logging
from datetime import datetime from datetime import datetime
from pathlib import Path
from typing import Any, Dict, List, Optional from typing import Any, Dict, List, Optional
from hermes_cli.config import get_hermes_home from hermes_cli.config import get_hermes_home
@ -90,7 +89,7 @@ def _build_discord(adapter) -> List[Dict[str, str]]:
return channels return channels
try: try:
import discord as _discord import discord as _discord # noqa: F401 — SDK presence check
except ImportError: except ImportError:
return channels return channels
@ -119,7 +118,6 @@ def _build_slack(adapter) -> List[Dict[str, str]]:
return _build_from_sessions("slack") return _build_from_sessions("slack")
try: try:
import asyncio
from tools.send_message_tool import _send_slack # noqa: F401 from tools.send_message_tool import _send_slack # noqa: F401
# Use the Slack Web API directly if available # Use the Slack Web API directly if available
except Exception: except Exception:

View file

@ -13,7 +13,6 @@ from pathlib import Path
from datetime import datetime from datetime import datetime
from dataclasses import dataclass from dataclasses import dataclass
from typing import Dict, List, Optional, Any, Union from typing import Dict, List, Optional, Any, Union
from enum import Enum
from hermes_cli.config import get_hermes_home from hermes_cli.config import get_hermes_home

View file

@ -21,8 +21,6 @@ Errors in hooks are caught and logged but never block the main pipeline.
import asyncio import asyncio
import importlib.util import importlib.util
import os
from pathlib import Path
from typing import Any, Callable, Dict, List, Optional from typing import Any, Callable, Dict, List, Optional
import yaml import yaml

View file

@ -12,7 +12,6 @@ the full SessionStore machinery.
import json import json
import logging import logging
from datetime import datetime from datetime import datetime
from pathlib import Path
from typing import Optional from typing import Optional
from hermes_cli.config import get_hermes_home from hermes_cli.config import get_hermes_home

View file

@ -20,7 +20,7 @@ import threading
import time import time
from collections import defaultdict from collections import defaultdict
from pathlib import Path from pathlib import Path
from typing import Callable, Dict, List, Optional, Any from typing import Callable, Dict, Optional, Any
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View file

@ -24,7 +24,6 @@ import re
import smtplib import smtplib
import ssl import ssl
import uuid import uuid
from datetime import datetime
from email.header import decode_header from email.header import decode_header
from email.mime.multipart import MIMEMultipart from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText from email.mime.text import MIMEText
@ -454,7 +453,6 @@ class EmailAdapter(BasePlatformAdapter):
async def send_typing(self, chat_id: str, metadata: Optional[Dict[str, Any]] = None) -> None: async def send_typing(self, chat_id: str, metadata: Optional[Dict[str, Any]] = None) -> None:
"""Email has no typing indicator — no-op.""" """Email has no typing indicator — no-op."""
pass
async def send_image( async def send_image(
self, self,

View file

@ -19,7 +19,7 @@ import os
import time import time
import uuid import uuid
from datetime import datetime from datetime import datetime
from typing import Any, Dict, List, Optional, Set from typing import Any, Dict, Optional, Set
try: try:
import aiohttp import aiohttp
@ -435,7 +435,6 @@ class HomeAssistantAdapter(BasePlatformAdapter):
async def send_typing(self, chat_id: str, metadata=None) -> None: async def send_typing(self, chat_id: str, metadata=None) -> None:
"""No typing indicator for Home Assistant.""" """No typing indicator for Home Assistant."""
pass
async def get_chat_info(self, chat_id: str) -> Dict[str, Any]: async def get_chat_info(self, chat_id: str) -> Dict[str, Any]:
"""Return basic info about the HA event channel.""" """Return basic info about the HA event channel."""

View file

@ -17,14 +17,13 @@ Environment variables:
from __future__ import annotations from __future__ import annotations
import asyncio import asyncio
import json
import logging import logging
import mimetypes import mimetypes
import os import os
import re import re
import time import time
from pathlib import Path from pathlib import Path
from typing import Any, Dict, List, Optional, Set from typing import Any, Dict, Optional, Set
from gateway.config import Platform, PlatformConfig from gateway.config import Platform, PlatformConfig
from gateway.platforms.base import ( from gateway.platforms.base import (

View file

@ -20,7 +20,7 @@ import os
import re import re
import time import time
from pathlib import Path from pathlib import Path
from typing import Any, Dict, List, Optional, Tuple from typing import Any, Dict, List, Optional
from gateway.config import Platform, PlatformConfig from gateway.config import Platform, PlatformConfig
from gateway.platforms.base import ( from gateway.platforms.base import (

View file

@ -12,7 +12,7 @@ import asyncio
import logging import logging
import os import os
import re import re
from typing import Dict, List, Optional, Any from typing import Dict, Optional, Any
try: try:
from slack_bolt.async_app import AsyncApp from slack_bolt.async_app import AsyncApp
@ -37,8 +37,6 @@ from gateway.platforms.base import (
SendResult, SendResult,
SUPPORTED_DOCUMENT_TYPES, SUPPORTED_DOCUMENT_TYPES,
cache_document_from_bytes, cache_document_from_bytes,
cache_image_from_url,
cache_audio_from_url,
) )

View file

@ -17,12 +17,11 @@ Gateway-specific env vars:
import asyncio import asyncio
import base64 import base64
import json
import logging import logging
import os import os
import re import re
import urllib.parse import urllib.parse
from typing import Any, Dict, List, Optional from typing import Any, Dict, Optional
from gateway.config import Platform, PlatformConfig from gateway.config import Platform, PlatformConfig
from gateway.platforms.base import ( from gateway.platforms.base import (

View file

@ -11,7 +11,7 @@ import asyncio
import logging import logging
import os import os
import re import re
from typing import Dict, List, Optional, Any from typing import Dict, Optional, Any
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View file

@ -16,7 +16,6 @@ with different backends via a bridge pattern.
""" """
import asyncio import asyncio
import json
import logging import logging
import os import os
import platform import platform
@ -24,7 +23,7 @@ import subprocess
_IS_WINDOWS = platform.system() == "Windows" _IS_WINDOWS = platform.system() == "Windows"
from pathlib import Path from pathlib import Path
from typing import Dict, List, Optional, Any from typing import Dict, Optional, Any
from hermes_cli.config import get_hermes_home from hermes_cli.config import get_hermes_home

View file

@ -220,7 +220,7 @@ from gateway.session import (
build_session_context_prompt, build_session_context_prompt,
build_session_key, build_session_key,
) )
from gateway.delivery import DeliveryRouter, DeliveryTarget from gateway.delivery import DeliveryRouter
from gateway.platforms.base import BasePlatformAdapter, MessageEvent, MessageType from gateway.platforms.base import BasePlatformAdapter, MessageEvent, MessageType
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -2771,8 +2771,6 @@ class GatewayRunner:
"""Handle /model command - show or change the current model.""" """Handle /model command - show or change the current model."""
import yaml import yaml
from hermes_cli.models import ( from hermes_cli.models import (
parse_model_input,
validate_requested_model,
curated_models_for_provider, curated_models_for_provider,
normalize_provider, normalize_provider,
_PROVIDER_LABELS, _PROVIDER_LABELS,

View file

@ -16,7 +16,7 @@ import re
import uuid import uuid
from pathlib import Path from pathlib import Path
from datetime import datetime, timedelta from datetime import datetime, timedelta
from dataclasses import dataclass, field from dataclasses import dataclass
from typing import Dict, List, Optional, Any from typing import Dict, List, Optional, Any
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -59,7 +59,7 @@ def _looks_like_phone(value: str) -> bool:
from .config import ( from .config import (
Platform, Platform,
GatewayConfig, GatewayConfig,
SessionResetPolicy, SessionResetPolicy, # noqa: F401 — re-exported via gateway/__init__.py
HomeChannel, HomeChannel,
) )

View file

@ -9,9 +9,7 @@ Cache location: ~/.hermes/sticker_cache.json
""" """
import json import json
import os
import time import time
from pathlib import Path
from typing import Optional from typing import Optional
from hermes_cli.config import get_hermes_home from hermes_cli.config import get_hermes_home

View file

@ -11,7 +11,7 @@ import subprocess
import threading import threading
import time import time
from pathlib import Path from pathlib import Path
from typing import Dict, List, Any, Optional from typing import Dict, List, Optional
from rich.console import Console from rich.console import Console
from rich.panel import Panel from rich.panel import Panel
@ -257,7 +257,7 @@ def build_welcome_banner(console: Console, model: str, cwd: str,
get_toolset_for_tool: Callable to map tool name -> toolset name. get_toolset_for_tool: Callable to map tool name -> toolset name.
context_length: Model's context window size in tokens. context_length: Model's context window size in tokens.
""" """
from model_tools import check_tool_availability, TOOLSET_REQUIREMENTS from model_tools import check_tool_availability
if get_toolset_for_tool is None: if get_toolset_for_tool is None:
from model_tools import get_toolset_for_tool from model_tools import get_toolset_for_tool

View file

@ -18,10 +18,8 @@ from hermes_cli.setup import (
print_header, print_header,
print_info, print_info,
print_success, print_success,
print_warning,
print_error, print_error,
prompt_yes_no, prompt_yes_no,
prompt_choice,
) )
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View file

@ -13,8 +13,7 @@ from __future__ import annotations
import os import os
import re import re
from collections.abc import Callable, Mapping from collections.abc import Callable, Mapping
from dataclasses import dataclass, field from dataclasses import dataclass
from pathlib import Path
from typing import Any from typing import Any
from prompt_toolkit.auto_suggest import AutoSuggest, Suggestion from prompt_toolkit.auto_suggest import AutoSuggest, Suggestion

View file

@ -21,12 +21,11 @@ from __future__ import annotations
import json import json
import logging import logging
import os import os
import re
import shutil import shutil
import subprocess import subprocess
import time import time
from pathlib import Path from pathlib import Path
from typing import Any, Optional from typing import Optional
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View file

@ -8,7 +8,6 @@ import os
import sys import sys
import subprocess import subprocess
import shutil import shutil
from pathlib import Path
from hermes_cli.config import get_project_root, get_hermes_home, get_env_path from hermes_cli.config import get_project_root, get_hermes_home, get_env_path
@ -448,7 +447,7 @@ def run_doctor(args):
check_fail("DAYTONA_API_KEY not set", "(required for TERMINAL_ENV=daytona)") check_fail("DAYTONA_API_KEY not set", "(required for TERMINAL_ENV=daytona)")
issues.append("Set DAYTONA_API_KEY environment variable") issues.append("Set DAYTONA_API_KEY environment variable")
try: try:
from daytona import Daytona from daytona import Daytona # noqa: F401 — SDK presence check
check_ok("daytona SDK", "(installed)") check_ok("daytona SDK", "(installed)")
except ImportError: except ImportError:
check_fail("daytona SDK not installed", "(pip install daytona)") check_fail("daytona SDK not installed", "(pip install daytona)")

View file

@ -4,7 +4,6 @@ from __future__ import annotations
import os import os
from pathlib import Path from pathlib import Path
from typing import Iterable
from dotenv import load_dotenv from dotenv import load_dotenv

View file

@ -548,7 +548,6 @@ def cmd_gateway(args):
def cmd_whatsapp(args): def cmd_whatsapp(args):
"""Set up WhatsApp: choose mode, configure, install bridge, pair via QR.""" """Set up WhatsApp: choose mode, configure, install bridge, pair via QR."""
import os
import subprocess import subprocess
from pathlib import Path from pathlib import Path
from hermes_cli.config import get_env_value, save_env_value from hermes_cli.config import get_env_value, save_env_value
@ -742,12 +741,9 @@ def cmd_setup(args):
def cmd_model(args): def cmd_model(args):
"""Select default model — starts with provider selection, then model picker.""" """Select default model — starts with provider selection, then model picker."""
from hermes_cli.auth import ( from hermes_cli.auth import (
resolve_provider, get_provider_auth_state, PROVIDER_REGISTRY, resolve_provider, AuthError, format_auth_error,
_prompt_model_selection, _save_model_choice, _update_config_for_provider,
resolve_nous_runtime_credentials, fetch_nous_models, AuthError, format_auth_error,
_login_nous,
) )
from hermes_cli.config import load_config, save_config, get_env_value, save_env_value from hermes_cli.config import load_config, get_env_value
config = load_config() config = load_config()
current_model = config.get("model") current_model = config.get("model")
@ -1983,7 +1979,7 @@ def _model_flow_api_key_provider(config, provider_id, current_model=""):
"""Generic flow for API-key providers (z.ai, MiniMax).""" """Generic flow for API-key providers (z.ai, MiniMax)."""
from hermes_cli.auth import ( from hermes_cli.auth import (
PROVIDER_REGISTRY, _prompt_model_selection, _save_model_choice, PROVIDER_REGISTRY, _prompt_model_selection, _save_model_choice,
_update_config_for_provider, deactivate_provider, deactivate_provider,
) )
from hermes_cli.config import get_env_value, save_env_value, load_config, save_config from hermes_cli.config import get_env_value, save_env_value, load_config, save_config
@ -2167,7 +2163,7 @@ def _model_flow_anthropic(config, current_model=""):
import os import os
from hermes_cli.auth import ( from hermes_cli.auth import (
PROVIDER_REGISTRY, _prompt_model_selection, _save_model_choice, PROVIDER_REGISTRY, _prompt_model_selection, _save_model_choice,
_update_config_for_provider, deactivate_provider, deactivate_provider,
) )
from hermes_cli.config import ( from hermes_cli.config import (
get_env_value, save_env_value, load_config, save_config, get_env_value, save_env_value, load_config, save_config,

View file

@ -14,15 +14,14 @@ import logging
import os import os
import re import re
import time import time
from pathlib import Path from typing import Any, Dict, List, Optional, Tuple
from typing import Any, Dict, List, Optional, Set, Tuple
from hermes_cli.config import ( from hermes_cli.config import (
load_config, load_config,
save_config, save_config,
get_env_value, get_env_value,
save_env_value, save_env_value,
get_hermes_home, get_hermes_home, # noqa: F401 — used by test mocks
) )
from hermes_cli.colors import Colors, color from hermes_cli.colors import Colors, color

View file

@ -13,9 +13,7 @@ concerns: state mutation, config persistence, output formatting.
from __future__ import annotations from __future__ import annotations
import os from dataclasses import dataclass
from dataclasses import dataclass, field
from typing import Optional
@dataclass @dataclass

View file

@ -283,7 +283,6 @@ from hermes_cli.config import (
save_env_value, save_env_value,
get_env_value, get_env_value,
ensure_hermes_home, ensure_hermes_home,
DEFAULT_CONFIG,
) )
from hermes_cli.colors import Colors, color from hermes_cli.colors import Colors, color
@ -798,15 +797,11 @@ def setup_model_provider(config: dict):
"""Configure the inference provider and default model.""" """Configure the inference provider and default model."""
from hermes_cli.auth import ( from hermes_cli.auth import (
get_active_provider, get_active_provider,
get_provider_auth_state,
PROVIDER_REGISTRY, PROVIDER_REGISTRY,
format_auth_error,
AuthError,
fetch_nous_models, fetch_nous_models,
resolve_nous_runtime_credentials, resolve_nous_runtime_credentials,
_update_config_for_provider, _update_config_for_provider,
_login_openai_codex, _login_openai_codex,
get_codex_auth_status,
resolve_codex_runtime_credentials, resolve_codex_runtime_credentials,
DEFAULT_CODEX_BASE_URL, DEFAULT_CODEX_BASE_URL,
detect_external_credentials, detect_external_credentials,
@ -975,7 +970,7 @@ def setup_model_provider(config: dict):
print() print()
try: try:
from hermes_cli.auth import _login_nous, ProviderConfig from hermes_cli.auth import _login_nous
import argparse import argparse
mock_args = argparse.Namespace( mock_args = argparse.Namespace(
@ -3303,7 +3298,6 @@ def _run_quick_setup(config: dict, hermes_home):
get_missing_env_vars, get_missing_env_vars,
get_missing_config_fields, get_missing_config_fields,
check_config_version, check_config_version,
migrate_config,
) )
print() print()

View file

@ -11,7 +11,7 @@ Config stored in ~/.hermes/config.yaml under:
telegram: [skill-c] telegram: [skill-c]
cli: [] cli: []
""" """
from typing import Dict, List, Optional, Set from typing import List, Optional, Set
from hermes_cli.config import load_config, save_config from hermes_cli.config import load_config, save_config
from hermes_cli.colors import Colors, color from hermes_cli.colors import Colors, color

View file

@ -186,7 +186,7 @@ def do_browse(page: int = 1, page_size: int = 20, source: str = "all",
Official skills are always shown first, regardless of source filter. Official skills are always shown first, regardless of source filter.
""" """
from tools.skills_hub import ( from tools.skills_hub import (
GitHubAuth, create_source_router, OptionalSkillSource, SkillMeta, GitHubAuth, create_source_router,
) )
# Clamp page_size to safe range # Clamp page_size to safe range

View file

@ -13,11 +13,9 @@ import sys
from pathlib import Path from pathlib import Path
from typing import Dict, List, Optional, Set from typing import Dict, List, Optional, Set
import os
from hermes_cli.config import ( from hermes_cli.config import (
load_config, save_config, get_env_value, save_env_value, load_config, save_config, get_env_value, save_env_value,
get_hermes_home,
) )
from hermes_cli.colors import Colors, color from hermes_cli.colors import Colors, color
@ -382,7 +380,7 @@ def _platform_toolset_summary(config: dict, platforms: Optional[List[str]] = Non
def _get_platform_tools(config: dict, platform: str) -> Set[str]: def _get_platform_tools(config: dict, platform: str) -> Set[str]:
"""Resolve which individual toolset names are enabled for a platform.""" """Resolve which individual toolset names are enabled for a platform."""
from toolsets import resolve_toolset, TOOLSETS from toolsets import resolve_toolset
platform_toolsets = config.get("platform_toolsets", {}) platform_toolsets = config.get("platform_toolsets", {})
toolset_names = platform_toolsets.get(platform) toolset_names = platform_toolsets.get(platform)

View file

@ -7,11 +7,9 @@ Provides options for:
""" """
import os import os
import sys
import shutil import shutil
import subprocess import subprocess
from pathlib import Path from pathlib import Path
from typing import Optional
from hermes_cli.colors import Colors, color from hermes_cli.colors import Colors, color

View file

@ -15,7 +15,7 @@ crashes due to a bad timezone string.
import logging import logging
import os import os
from datetime import datetime, timezone as _tz from datetime import datetime
from pathlib import Path from pathlib import Path
from typing import Optional from typing import Optional

View file

@ -53,8 +53,7 @@ else:
# Import agent and tools # Import agent and tools
from run_agent import AIAgent from run_agent import AIAgent
from model_tools import get_tool_definitions, check_toolset_requirements from tools.rl_training_tool import get_missing_keys
from tools.rl_training_tool import check_rl_api_keys, get_missing_keys
# ============================================================================ # ============================================================================

View file

@ -65,7 +65,6 @@ from tools.terminal_tool import cleanup_vm
from tools.interrupt import set_interrupt as _set_interrupt from tools.interrupt import set_interrupt as _set_interrupt
from tools.browser_tool import cleanup_browser from tools.browser_tool import cleanup_browser
import requests
from hermes_constants import OPENROUTER_BASE_URL from hermes_constants import OPENROUTER_BASE_URL

View file

@ -23,7 +23,6 @@ import logging
import os import os
import shutil import shutil
import subprocess import subprocess
import time
from pathlib import Path from pathlib import Path
from typing import Dict, List, Optional, Set from typing import Dict, List, Optional, Set

View file

@ -12,7 +12,7 @@ a thin dispatcher that delegates to a platform-provided callback.
""" """
import json import json
from typing import Dict, Any, List, Optional, Callable from typing import List, Optional, Callable
# Maximum number of predefined choices the agent can offer. # Maximum number of predefined choices the agent can offer.

View file

@ -171,7 +171,6 @@ def _build_child_agent(
model on OpenRouter while the parent runs on Nous Portal). model on OpenRouter while the parent runs on Nous Portal).
""" """
from run_agent import AIAgent from run_agent import AIAgent
import model_tools
# When no explicit toolsets given, inherit from parent's enabled toolsets # When no explicit toolsets given, inherit from parent's enabled toolsets
# so disabled tools (e.g. web) don't leak to subagents. # so disabled tools (e.g. web) don't leak to subagents.

View file

@ -27,11 +27,10 @@ Usage:
import os import os
import re import re
import json
import difflib import difflib
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import Optional, List, Dict, Any, Tuple from typing import Optional, List, Dict, Any
from pathlib import Path from pathlib import Path

View file

@ -4,9 +4,7 @@
import errno import errno
import json import json
import logging import logging
import os
import threading import threading
from typing import Optional
from tools.file_operations import ShellFileOperations from tools.file_operations import ShellFileOperations
from agent.redact import redact_sensitive_text from agent.redact import redact_sensitive_text
@ -50,8 +48,8 @@ def _get_file_ops(task_id: str = "default") -> ShellFileOperations:
from tools.terminal_tool import ( from tools.terminal_tool import (
_active_environments, _env_lock, _create_environment, _active_environments, _env_lock, _create_environment,
_get_env_config, _last_activity, _start_cleanup_thread, _get_env_config, _last_activity, _start_cleanup_thread,
_check_disk_usage_warning, _creation_locks,
_creation_locks, _creation_locks_lock, _creation_locks_lock,
) )
import time import time

View file

@ -416,7 +416,7 @@ def check_image_generation_requirements() -> bool:
return False return False
# Check if fal_client is available # Check if fal_client is available
import fal_client import fal_client # noqa: F401 — SDK presence check
return True return True
except ImportError: except ImportError:

View file

@ -34,7 +34,6 @@ import logging
import os import os
import platform import platform
import shlex import shlex
import shutil
import signal import signal
import subprocess import subprocess
import threading import threading
@ -44,7 +43,6 @@ import uuid
_IS_WINDOWS = platform.system() == "Windows" _IS_WINDOWS = platform.system() == "Windows"
from tools.environments.local import _find_shell, _sanitize_subprocess_env from tools.environments.local import _find_shell, _sanitize_subprocess_env
from dataclasses import dataclass, field from dataclasses import dataclass, field
from pathlib import Path
from typing import Any, Dict, List, Optional from typing import Any, Dict, List, Optional
from hermes_cli.config import get_hermes_home from hermes_cli.config import get_hermes_home

View file

@ -16,7 +16,7 @@ Import chain (circular-import safe):
import json import json
import logging import logging
from typing import Any, Callable, Dict, List, Optional, Set from typing import Callable, Dict, List, Optional, Set
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View file

@ -40,7 +40,7 @@ import uuid
import logging import logging
from datetime import datetime from datetime import datetime
import yaml import yaml
from dataclasses import dataclass, field from dataclasses import dataclass
from pathlib import Path from pathlib import Path
from typing import Any, Dict, List, Optional from typing import Any, Dict, List, Optional

View file

@ -379,7 +379,7 @@ async def _send_telegram(token, chat_id, message, media_files=None, thread_id=No
else: else:
# Reuse the gateway adapter's format_message for markdown→MarkdownV2 # Reuse the gateway adapter's format_message for markdown→MarkdownV2
try: try:
from gateway.platforms.telegram import TelegramAdapter, _escape_mdv2, _strip_mdv2 from gateway.platforms.telegram import TelegramAdapter, _strip_mdv2
_adapter = TelegramAdapter.__new__(TelegramAdapter) _adapter = TelegramAdapter.__new__(TelegramAdapter)
formatted = _adapter.format_message(message) formatted = _adapter.format_message(message)
except Exception: except Exception:

View file

@ -18,7 +18,6 @@ Flow:
import asyncio import asyncio
import concurrent.futures import concurrent.futures
import json import json
import os
import logging import logging
from typing import Dict, Any, List, Optional, Union from typing import Dict, Any, List, Optional, Union

View file

@ -32,7 +32,7 @@ import httpx
import yaml import yaml
from tools.skills_guard import ( from tools.skills_guard import (
ScanResult, scan_skill, should_allow_install, content_hash, TRUSTED_REPOS, ScanResult, content_hash, TRUSTED_REPOS,
) )
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View file

@ -31,7 +31,6 @@ import json
import logging import logging
import os import os
import platform import platform
import sys
import time import time
import threading import threading
import atexit import atexit
@ -48,7 +47,7 @@ logger = logging.getLogger(__name__)
# The terminal tool polls this during command execution so it can kill # The terminal tool polls this during command execution so it can kill
# long-running subprocesses immediately instead of blocking until timeout. # long-running subprocesses immediately instead of blocking until timeout.
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
from tools.interrupt import is_interrupted, _interrupt_event from tools.interrupt import is_interrupted, _interrupt_event # noqa: F401 — re-exported
# ============================================================================= # =============================================================================
@ -1232,7 +1231,7 @@ def check_terminal_requirements() -> bool:
return True return True
elif env_type == "daytona": elif env_type == "daytona":
from daytona import Daytona from daytona import Daytona # noqa: F401 — SDK presence check
return os.getenv("DAYTONA_API_KEY") is not None return os.getenv("DAYTONA_API_KEY") is not None
else: else:

View file

@ -629,7 +629,6 @@ def stream_tts_to_speaker(
if client is not None: if client is not None:
try: try:
sd = _import_sounddevice() sd = _import_sounddevice()
import numpy as _np
output_stream = sd.OutputStream( output_stream = sd.OutputStream(
samplerate=24000, channels=1, dtype="int16", samplerate=24000, channels=1, dtype="int16",
) )

View file

@ -28,7 +28,6 @@ Usage:
) )
""" """
import asyncio
import base64 import base64
import json import json
import logging import logging

View file

@ -19,7 +19,6 @@ import tempfile
import threading import threading
import time import time
import wave import wave
from pathlib import Path
from typing import Any, Dict, List, Optional from typing import Any, Dict, List, Optional
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -710,7 +709,7 @@ def check_voice_requirements() -> Dict[str, Any]:
``missing_packages``, and ``details``. ``missing_packages``, and ``details``.
""" """
# Determine STT provider availability # Determine STT provider availability
from tools.transcription_tools import _get_provider, _load_stt_config, is_stt_enabled, _HAS_FASTER_WHISPER from tools.transcription_tools import _get_provider, _load_stt_config, is_stt_enabled
stt_config = _load_stt_config() stt_config = _load_stt_config()
stt_enabled = is_stt_enabled(stt_config) stt_enabled = is_stt_enabled(stt_config)
stt_provider = _get_provider(stt_config) stt_provider = _get_provider(stt_config)