chore: prune unused imports and duplicate import redefinitions

Remove unused imports (F401) and duplicate/shadowed import
redefinitions (F811) across the codebase using ruff's safe
autofixes. No behavioral changes -- imports only.

- ~1400 safe autofixes applied across 644 files (net -1072 lines)
- __init__.py re-exports preserved (excluded from F401 removal so
  public re-export surfaces stay intact)
- Re-exports that are imported or monkeypatched by tests but look
  unused in their defining module are kept with explicit # noqa:
  F401 (gateway/run.py load_dotenv; run_agent re-exports from
  agent.message_sanitization, agent.context_compressor,
  agent.retry_utils, agent.prompt_builder, agent.process_bootstrap,
  agent.codex_responses_adapter)
- Unsafe F841 (unused-variable) fixes deliberately skipped -- those
  can change behavior when the RHS has side effects
- ruff lints remain disabled in pyproject.toml (only PLW1514 is
  selected); this is a one-time cleanup, not a config change

Verification:
- python -m compileall: clean
- pytest --collect-only: all 27161 tests collect (zero import errors)
- core entry points import clean (run_agent, model_tools, cli,
  toolsets, hermes_state, batch_runner, gateway)
- static scan: every name any test imports directly from an edited
  module still resolves
This commit is contained in:
kshitijk4poor 2026-05-29 02:04:58 +05:30 committed by Teknium
parent a4d8f0f62a
commit 66827f8947
644 changed files with 254 additions and 1326 deletions

View File

@ -27,7 +27,6 @@ import threading
import time import time
import uuid import uuid
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 urllib.parse import urlparse, parse_qs, urlunparse from urllib.parse import urlparse, parse_qs, urlunparse
@ -37,7 +36,6 @@ from agent.memory_manager import StreamingContextScrubber
from agent.model_metadata import ( from agent.model_metadata import (
MINIMUM_CONTEXT_LENGTH, MINIMUM_CONTEXT_LENGTH,
fetch_model_metadata, fetch_model_metadata,
get_model_context_length,
is_local_endpoint, is_local_endpoint,
query_ollama_num_ctx, query_ollama_num_ctx,
) )
@ -52,7 +50,6 @@ from agent.tool_guardrails import (
from hermes_cli.config import cfg_get from hermes_cli.config import cfg_get
from hermes_cli.timeouts import get_provider_request_timeout from hermes_cli.timeouts import get_provider_request_timeout
from hermes_constants import get_hermes_home from hermes_constants import get_hermes_home
from model_tools import check_toolset_requirements, get_tool_definitions
from utils import base_url_host_matches from utils import base_url_host_matches
# Use the same logger name as run_agent so tests patching ``run_agent.logger`` # 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 # Reject models whose context window is below the minimum required
# for reliable tool-calling workflows (64K tokens). # for reliable tool-calling workflows (64K tokens).
from agent.model_metadata import MINIMUM_CONTEXT_LENGTH
_ctx = getattr(agent.context_compressor, "context_length", 0) _ctx = getattr(agent.context_compressor, "context_length", 0)
if _ctx and _ctx < MINIMUM_CONTEXT_LENGTH: if _ctx and _ctx < MINIMUM_CONTEXT_LENGTH:
raise ValueError( raise ValueError(

View File

@ -25,24 +25,17 @@ from __future__ import annotations
import copy import copy
import json import json
import logging import logging
import os
import re import re
import threading
import time import time
import uuid
from datetime import datetime from datetime import datetime
from pathlib import Path 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 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.tool_dispatch_helpers import _trajectory_normalize_msg, make_tool_result_message
from agent.trajectory import convert_scratchpad_to_think from agent.trajectory import convert_scratchpad_to_think
from agent.credential_pool import STATUS_EXHAUSTED 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 from utils import base_url_host_matches, base_url_hostname, env_var_enabled, atomic_json_write
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View File

@ -15,49 +15,23 @@ sites unchanged. Symbols that tests patch on ``run_agent`` (e.g.
from __future__ import annotations from __future__ import annotations
import concurrent.futures
import contextvars
import copy
import json import json
import logging import logging
import os import os
import random
import re import re
import sys
import threading import threading
import time import time
import uuid import uuid
from datetime import datetime
from pathlib import Path
from types import SimpleNamespace from types import SimpleNamespace
from typing import Any, Dict, List, Optional, Tuple from typing import Any, Dict, Optional
from urllib.parse import urlparse, parse_qs, urlunparse
from hermes_cli.timeouts import get_provider_request_timeout, get_provider_stale_timeout 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 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.model_metadata import is_local_endpoint
from agent.message_sanitization import ( from agent.message_sanitization import (
_sanitize_surrogates, _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, _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 tools.terminal_tool import is_persistent_env
from utils import base_url_host_matches, base_url_hostname from utils import base_url_host_matches, base_url_hostname

View File

@ -16,7 +16,6 @@ compatibility.
from __future__ import annotations from __future__ import annotations
import json
import logging import logging
import os import os
import time import time

View File

@ -34,7 +34,7 @@ import tempfile
import uuid import uuid
from datetime import datetime from datetime import datetime
from pathlib import Path 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 from agent.model_metadata import estimate_request_tokens_rough

View File

@ -27,8 +27,6 @@ import time
import uuid import uuid
from typing import Any, Dict, List, Optional 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.codex_responses_adapter import _summarize_user_message_for_log
from agent.display import KawaiiSpinner from agent.display import KawaiiSpinner
from agent.error_classifier import FailoverReason, classify_api_error from agent.error_classifier import FailoverReason, classify_api_error
@ -53,20 +51,13 @@ from agent.model_metadata import (
parse_available_output_tokens_from_error, parse_available_output_tokens_from_error,
save_context_length, 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.process_bootstrap import _install_safe_stdio
from agent.prompt_caching import apply_anthropic_cache_control from agent.prompt_caching import apply_anthropic_cache_control
from agent.retry_utils import jittered_backoff from agent.retry_utils import jittered_backoff
from agent.trajectory import has_incomplete_scratchpad from agent.trajectory import has_incomplete_scratchpad
from agent.usage_pricing import estimate_usage_cost, normalize_usage 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 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 tools.skill_provenance import set_current_write_origin
from utils import base_url_host_matches, env_var_enabled 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 # Tag all log records on this thread with the session ID so
# ``hermes logs --session <id>`` can filter a single conversation. # ``hermes logs --session <id>`` can filter a single conversation.
from hermes_logging import set_session_context
set_session_context(agent.session_id) set_session_context(agent.session_id)
# Bind the skill write-origin ContextVar for this thread so tool # 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; # a foreground user-directed turn. Set at the top of each call;
# the review fork runs on its own thread with a fresh context, # the review fork runs on its own thread with a fresh context,
# so the foreground value here does not leak into it. # 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")) set_current_write_origin(getattr(agent, "_memory_write_origin", "assistant_tool"))
# If the previous turn activated fallback, restore the primary # If the previous turn activated fallback, restore the primary

View File

@ -14,7 +14,7 @@ from datetime import datetime, timezone
from typing import Any, Dict, List, Optional, Set, Tuple from typing import Any, Dict, List, Optional, Set, Tuple
from hermes_constants import OPENROUTER_BASE_URL 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 ( from agent.credential_persistence import (
is_borrowed_credential_source, is_borrowed_credential_source,
sanitize_borrowed_credential_payload, sanitize_borrowed_credential_payload,

View File

@ -39,12 +39,9 @@ from __future__ import annotations
import json import json
import logging import logging
import os
import re import re
import shutil import shutil
import tarfile import tarfile
import tempfile
import time
from datetime import datetime, timezone from datetime import datetime, timezone
from pathlib import Path from pathlib import Path
from typing import Any, Dict, List, Optional, Tuple from typing import Any, Dict, List, Optional, Tuple

View File

@ -31,7 +31,6 @@ import json
import logging import logging
import time import time
import urllib.error import urllib.error
import urllib.parse
import urllib.request import urllib.request
import uuid import uuid
from dataclasses import dataclass, field from dataclasses import dataclass, field

View File

@ -16,7 +16,6 @@ from __future__ import annotations
import argparse import argparse
import sys import sys
from typing import Optional
def register_subparser(subparsers: argparse._SubParsersAction) -> None: def register_subparser(subparsers: argparse._SubParsersAction) -> None:
@ -249,7 +248,6 @@ def _cmd_restart() -> int:
def _cmd_which(server_id: str) -> int: def _cmd_which(server_id: str) -> int:
from agent.lsp.install import INSTALL_RECIPES, hermes_lsp_bin_dir from agent.lsp.install import INSTALL_RECIPES, hermes_lsp_bin_dir
import os
import shutil as _shutil import shutil as _shutil
recipe = INSTALL_RECIPES.get(server_id) recipe = INSTALL_RECIPES.get(server_id)

View File

@ -39,25 +39,20 @@ import logging
import os import os
import threading import threading
import time import time
from concurrent.futures import Future as ConcurrentFuture
from typing import Any, Callable, Dict, List, Optional, Tuple from typing import Any, Callable, Dict, List, Optional, Tuple
from agent.lsp import eventlog from agent.lsp import eventlog
from agent.lsp.client import ( from agent.lsp.client import (
DIAGNOSTICS_DOCUMENT_WAIT, DIAGNOSTICS_DOCUMENT_WAIT,
LSPClient, LSPClient,
file_uri,
) )
from agent.lsp.servers import ( from agent.lsp.servers import (
ServerContext, ServerContext,
ServerDef,
SpawnSpec,
find_server_for_file, find_server_for_file,
language_id_for, language_id_for,
) )
from agent.lsp.workspace import ( from agent.lsp.workspace import (
clear_cache, clear_cache,
is_inside_workspace,
resolve_workspace_for_file, resolve_workspace_for_file,
) )

View File

@ -25,7 +25,7 @@ import shutil
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple 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") logger = logging.getLogger("agent.lsp.servers")

View File

@ -7,7 +7,6 @@ assemble pieces, then combines them with memory and ephemeral prompts.
import json import json
import logging import logging
import os import os
import re
import threading import threading
from collections import OrderedDict from collections import OrderedDict
from pathlib import Path from pathlib import Path

View File

@ -37,7 +37,6 @@ import platform
import shutil import shutil
import stat import stat
import subprocess import subprocess
import sys
import tempfile import tempfile
import time import time
import urllib.error import urllib.error

View File

@ -20,7 +20,7 @@ import os
import random import random
import threading import threading
import time import time
from typing import Any, Optional from typing import Optional
from agent.display import ( from agent.display import (
KawaiiSpinner, KawaiiSpinner,

View File

@ -10,7 +10,7 @@ reasoning configuration, temperature handling, and extra_body assembly.
""" """
import copy import copy
from typing import Any, Dict, List, Optional from typing import Any, Dict
from agent.lmstudio_reasoning import resolve_lmstudio_effort from agent.lmstudio_reasoning import resolve_lmstudio_effort
from agent.moonshot_schema import is_moonshot_model, sanitize_moonshot_tools from agent.moonshot_schema import is_moonshot_model, sanitize_moonshot_tools

View File

@ -23,7 +23,7 @@ import subprocess
import threading import threading
import time import time
from dataclasses import dataclass, field 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 # 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. # `codex --version` parsed at install time; bumping is a one-line change here.

View File

@ -126,7 +126,6 @@ from gateway.platforms.qqbot.chunked_upload import (
) )
from gateway.platforms.qqbot.keyboards import ( from gateway.platforms.qqbot.keyboards import (
ApprovalRequest, ApprovalRequest,
ApprovalSender,
InlineKeyboard, InlineKeyboard,
InteractionEvent, InteractionEvent,
build_approval_keyboard, build_approval_keyboard,

View File

@ -37,7 +37,7 @@ import asyncio
import functools import functools
import hashlib import hashlib
import logging import logging
from dataclasses import dataclass, field from dataclasses import dataclass
from pathlib import Path from pathlib import Path
from typing import Any, Awaitable, Callable, Dict, List, Optional from typing import Any, Awaitable, Callable, Dict, List, Optional

View File

@ -1690,7 +1690,6 @@ class TelegramAdapter(BasePlatformAdapter):
BotCommandScopeAllPrivateChats, BotCommandScopeAllPrivateChats,
BotCommandScopeAllGroupChats, BotCommandScopeAllGroupChats,
BotCommandScopeDefault, BotCommandScopeDefault,
BotCommandScopeChat,
) )
from hermes_cli.commands import telegram_menu_commands from hermes_cli.commands import telegram_menu_commands
# Telegram allows up to 100 commands but has an undocumented # Telegram allows up to 100 commands but has an undocumented

View File

@ -751,7 +751,7 @@ _hermes_home = get_hermes_home()
# Load environment variables from ~/.hermes/.env first. # Load environment variables from ~/.hermes/.env first.
# User-managed env files should override stale shell exports on restart. # 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 from hermes_cli.env_loader import load_hermes_dotenv
_env_path = _hermes_home / '.env' _env_path = _hermes_home / '.env'
load_hermes_dotenv(hermes_home=_hermes_home, project_env=Path(__file__).resolve().parents[1] / '.env') load_hermes_dotenv(hermes_home=_hermes_home, project_env=Path(__file__).resolve().parents[1] / '.env')

View File

@ -26,7 +26,6 @@ piecemeal, the footer is sent as a separate trailing message via
from __future__ import annotations from __future__ import annotations
import os import os
from pathlib import Path
from typing import Any, Iterable, Optional from typing import Any, Iterable, Optional
_DEFAULT_FIELDS: tuple[str, ...] = ("model", "context_pct", "cwd") _DEFAULT_FIELDS: tuple[str, ...] = ("model", "context_pct", "cwd")

View File

@ -27,11 +27,9 @@ guarantee.
from __future__ import annotations from __future__ import annotations
import os
import shutil import shutil
import subprocess
import sys import sys
from typing import Optional, Sequence from typing import Sequence
__all__ = [ __all__ = [
"IS_WINDOWS", "IS_WINDOWS",

View File

@ -45,7 +45,6 @@ from typing import Any, Callable, Dict, FrozenSet, List, Optional, Tuple
from urllib.parse import parse_qs, urlencode, urlparse from urllib.parse import parse_qs, urlencode, urlparse
import httpx import httpx
import yaml
from hermes_cli.config import get_hermes_home, get_config_path, read_raw_config from hermes_cli.config import get_hermes_home, get_config_path, read_raw_config
from hermes_constants import OPENROUTER_BASE_URL, secure_parent_dir from hermes_constants import OPENROUTER_BASE_URL, secure_parent_dir

View File

@ -15,7 +15,7 @@ Subcommands:
from __future__ import annotations from __future__ import annotations
import sys import sys
from typing import List, Optional from typing import List
from rich.console import Console from rich.console import Console
from rich.table import Table from rich.table import Table

View File

@ -25,7 +25,7 @@ import argparse
import time import time
from datetime import datetime from datetime import datetime
from pathlib import Path from pathlib import Path
from typing import Any, Dict from typing import Any
def _fmt_bytes(n: int) -> str: def _fmt_bytes(n: int) -> str:

View File

@ -17,8 +17,6 @@ import logging
import re import re
import sys import sys
import time import time
import urllib.error
import urllib.parse
import urllib.request import urllib.request
from dataclasses import dataclass from dataclasses import dataclass
from pathlib import Path from pathlib import Path

View File

@ -8,7 +8,6 @@ import os
import sys import sys
import subprocess import subprocess
import shutil import shutil
import importlib.util
from pathlib import Path 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

View File

@ -84,7 +84,6 @@ import threading
import logging import logging
import time import time
from dataclasses import dataclass, field from dataclasses import dataclass, field
from datetime import datetime
from pathlib import Path from pathlib import Path
from typing import Any, Iterable, Optional from typing import Any, Iterable, Optional
@ -4743,7 +4742,6 @@ def detect_stale_running(
if stale_timeout_seconds <= 0: if stale_timeout_seconds <= 0:
return [] return []
import signal as _signal_mod
now = int(time.time()) now = int(time.time())
host_prefix = f"{_claimer_id().split(':', 1)[0]}:" host_prefix = f"{_claimer_id().split(':', 1)[0]}:"
@ -6483,7 +6481,7 @@ def _to_epoch(val) -> Optional[int]:
pass pass
# ISO-8601 fallback (e.g. '2026-05-10T15:00:00Z') # ISO-8601 fallback (e.g. '2026-05-10T15:00:00Z')
try: try:
from datetime import datetime, timezone from datetime import datetime
dt = datetime.fromisoformat(s.replace("Z", "+00:00")) dt = datetime.fromisoformat(s.replace("Z", "+00:00"))
return int(dt.timestamp()) return int(dt.timestamp())
except (ValueError, OSError): except (ValueError, OSError):

View File

@ -5593,7 +5593,6 @@ def _model_flow_bedrock(config, current_model=""):
def _model_flow_api_key_provider(config, provider_id, current_model=""): def _model_flow_api_key_provider(config, provider_id, current_model=""):
"""Generic flow for API-key providers (z.ai, MiniMax, OpenCode, etc.).""" """Generic flow for API-key providers (z.ai, MiniMax, OpenCode, etc.)."""
from hermes_cli.auth import ( from hermes_cli.auth import (
LMSTUDIO_NOAUTH_PLACEHOLDER,
PROVIDER_REGISTRY, PROVIDER_REGISTRY,
_prompt_model_selection, _prompt_model_selection,
_save_model_choice, _save_model_choice,

View File

@ -23,7 +23,6 @@ See references/mcp-catalog.md (this repo's skill) for the manifest schema.
from __future__ import annotations from __future__ import annotations
import os
import re import re
import shutil import shutil
import subprocess import subprocess
@ -41,7 +40,7 @@ from hermes_cli.config import (
get_env_value, get_env_value,
save_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 _MANIFEST_VERSION = 1

View File

@ -1085,8 +1085,7 @@ def list_authenticated_providers(
from hermes_cli.auth import PROVIDER_REGISTRY from hermes_cli.auth import PROVIDER_REGISTRY
from hermes_cli.models import ( from hermes_cli.models import (
OPENROUTER_MODELS, _PROVIDER_MODELS, OPENROUTER_MODELS, _PROVIDER_MODELS,
_MODELS_DEV_PREFERRED, _merge_with_models_dev, provider_model_ids, _MODELS_DEV_PREFERRED, _merge_with_models_dev, cached_provider_model_ids,
cached_provider_model_ids,
get_curated_nous_model_ids, get_curated_nous_model_ids,
) )

View File

@ -34,7 +34,6 @@ so plugin-defined tools appear alongside the built-in tools.
from __future__ import annotations from __future__ import annotations
import asyncio import asyncio
import importlib
import importlib.metadata import importlib.metadata
import importlib.util import importlib.util
import inspect import inspect

View File

@ -13,7 +13,6 @@ from __future__ import annotations
import sys import sys
import webbrowser import webbrowser
from typing import Optional
from hermes_cli.colors import Colors, color from hermes_cli.colors import Colors, color
from hermes_cli.config import load_config from hermes_cli.config import load_config

View File

@ -28,7 +28,6 @@ from __future__ import annotations
import json import json
import logging import logging
import os
import re import re
from dataclasses import dataclass from dataclasses import dataclass
from pathlib import Path from pathlib import Path

View File

@ -940,7 +940,6 @@ def delete_profile(name: str, yes: bool = False) -> Path:
``sys.exc_info()`` tuple). ``sys.exc_info()`` tuple).
""" """
import stat as _stat import stat as _stat
import sys as _sys
# Normalise the two callback signatures: # Normalise the two callback signatures:
# onexc(func, path, exc_instance) — 3.12+ # onexc(func, path, exc_instance) — 3.12+

View File

@ -12,7 +12,6 @@ or rewrite request/response bodies. It's a credential-attaching forwarder.
from __future__ import annotations from __future__ import annotations
import asyncio import asyncio
import json
import logging import logging
import signal import signal
from typing import Optional from typing import Optional

View File

@ -14,9 +14,8 @@ import argparse
import json import json
import os import os
import subprocess import subprocess
import sys
from pathlib import Path from pathlib import Path
from typing import List, Optional, Tuple from typing import List, Optional
from rich.console import Console from rich.console import Console
from rich.panel import Panel from rich.panel import Panel

View File

@ -36,7 +36,7 @@ from __future__ import annotations
import logging import logging
import os import os
import sys import sys
from dataclasses import dataclass, field from dataclasses import dataclass
from pathlib import Path from pathlib import Path
from typing import Iterable, Optional from typing import Iterable, Optional

View File

@ -28,7 +28,7 @@ import urllib.error
import urllib.request import urllib.request
from dataclasses import dataclass, field from dataclasses import dataclass, field
from pathlib import Path from pathlib import Path
from typing import Any, Iterable, Optional from typing import Iterable, Optional
from hermes_constants import get_hermes_home from hermes_constants import get_hermes_home

View File

@ -12,7 +12,6 @@ Config files are stored in ~/.hermes/ for easy access.
""" """
import importlib.util import importlib.util
import json
import logging import logging
import os import os
import re import re

View File

@ -7,7 +7,6 @@ Shows the status of all Hermes Agent components.
import os import os
import sys import sys
import subprocess # noqa: F401 — re-exported for tests that monkeypatch status.subprocess to guard against regressions import subprocess # noqa: F401 — re-exported for tests that monkeypatch status.subprocess to guard against regressions
import importlib.util
from pathlib import Path from pathlib import Path
PROJECT_ROOT = Path(__file__).parent.parent.resolve() PROJECT_ROOT = Path(__file__).parent.parent.resolve()

View File

@ -216,7 +216,6 @@ def _augment_path_with_known_tools() -> None:
if not is_windows(): if not is_windows():
return return
import shutil as _shutil
local_appdata = os.environ.get("LOCALAPPDATA", "") local_appdata = os.environ.get("LOCALAPPDATA", "")
if not local_appdata: if not local_appdata:

View File

@ -3351,7 +3351,6 @@ async def get_models_analytics(days: int = 30):
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
import re import re
import asyncio
# PTY bridge is POSIX-only (depends on fcntl/termios/ptyprocess). On native # 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 # Windows the import raises; catch and leave PtyBridge=None so the rest of

View File

@ -29,12 +29,8 @@ Usage:
import json import json
import logging import logging
import os import os
import sys
import time
import uuid
from datetime import datetime from datetime import datetime
from pathlib import Path from typing import List, Dict, Any, Optional
from typing import List, Dict, Any, Optional, Literal
import fire import fire
from dotenv import load_dotenv from dotenv import load_dotenv

View File

@ -18,7 +18,6 @@ unknown templates get smart default text positioning based on their box_count.
import json import json
import os import os
import sys import sys
import textwrap
from io import BytesIO from io import BytesIO
from pathlib import Path from pathlib import Path

View File

@ -7,7 +7,6 @@ Validates Excel DCF models for formula errors and common DCF mistakes
import sys import sys
import json import json
from pathlib import Path from pathlib import Path
from typing import Optional
class DCFModelValidator: class DCFModelValidator:

View File

@ -16,7 +16,6 @@ import json
import time import time
import urllib.request import urllib.request
import urllib.parse import urllib.parse
import urllib.error
API_KEY = os.environ.get("USDA_API_KEY", "DEMO_KEY") API_KEY = os.environ.get("USDA_API_KEY", "DEMO_KEY")
BASE = "https://api.nal.usda.gov/fdc/v1" BASE = "https://api.nal.usda.gov/fdc/v1"

View File

@ -5,7 +5,7 @@ Usage: python3 chembl_target.py "EGFR" --min-pchembl 7 --limit 20
No external dependencies. No external dependencies.
""" """
import sys, json, time, argparse 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" BASE = "https://www.ebi.ac.uk/chembl/api/data"

View File

@ -4,8 +4,8 @@ ro5_screen.py — Batch Lipinski Ro5 + Veber screening via PubChem API.
Usage: python3 ro5_screen.py aspirin ibuprofen paracetamol Usage: python3 ro5_screen.py aspirin ibuprofen paracetamol
No external dependencies beyond stdlib. No external dependencies beyond stdlib.
""" """
import sys, json, time, argparse import sys, json, time
import urllib.request, urllib.parse, urllib.error import urllib.request, urllib.parse
BASE = "https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/name" BASE = "https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/name"
PROPS = "MolecularWeight,XLogP,HBondDonorCount,HBondAcceptorCount,RotatableBondCount,TPSA" PROPS = "MolecularWeight,XLogP,HBondDonorCount,HBondAcceptorCount,RotatableBondCount,TPSA"

View File

@ -11,7 +11,6 @@ from __future__ import annotations
import argparse import argparse
import csv import csv
import json
import sys import sys
import time import time
import urllib.parse import urllib.parse

View File

@ -12,7 +12,6 @@ from __future__ import annotations
import argparse import argparse
import csv import csv
import json
import os import os
import re import re
import sys import sys

View File

@ -12,7 +12,6 @@ from __future__ import annotations
import argparse import argparse
import csv import csv
import json
import re import re
import sys import sys
import urllib.parse import urllib.parse

View File

@ -19,7 +19,6 @@ import argparse
import csv import csv
import datetime as dt import datetime as dt
import json import json
import math
import random import random
import statistics import statistics
from collections import defaultdict from collections import defaultdict

View File

@ -13,7 +13,6 @@ from __future__ import annotations
import argparse import argparse
import json import json
import os
import sys import sys
from pathlib import Path from pathlib import Path
from typing import Optional from typing import Optional

View File

@ -49,8 +49,7 @@ from gateway.platforms.base import (
MessageEvent, MessageEvent,
MessageType, MessageType,
) )
from gateway.session import SessionSource from gateway.config import Platform
from gateway.config import PlatformConfig, Platform
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------

View File

@ -76,7 +76,7 @@ import time
import uuid import uuid
from dataclasses import dataclass, field from dataclasses import dataclass, field
from pathlib import Path 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 from urllib.parse import quote as _urlquote
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -95,7 +95,6 @@ from gateway.platforms.base import (
cache_image_from_bytes, cache_image_from_bytes,
) )
from gateway.config import Platform from gateway.config import Platform
from gateway.session import SessionSource
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------

View File

@ -2,7 +2,7 @@
from __future__ import annotations from __future__ import annotations
from typing import Any, Dict, List from typing import Any, List
from hermes_cli.auth import get_auth_status from hermes_cli.auth import get_auth_status
from plugins.spotify.client import ( from plugins.spotify.client import (

View File

@ -24,7 +24,6 @@ from plugins.teams_pipeline.store import TeamsPipelineStore, resolve_teams_pipel
from plugins.teams_pipeline.subscriptions import ( from plugins.teams_pipeline.subscriptions import (
build_graph_client, build_graph_client,
maintain_graph_subscriptions, maintain_graph_subscriptions,
sync_graph_subscription_record,
) )
from tools.microsoft_graph_auth import MicrosoftGraphConfigError, MicrosoftGraphTokenProvider from tools.microsoft_graph_auth import MicrosoftGraphConfigError, MicrosoftGraphTokenProvider

View File

@ -7,7 +7,6 @@ import json
import logging import logging
import os import os
import shutil import shutil
import subprocess
import tempfile import tempfile
import uuid import uuid
from dataclasses import dataclass from dataclasses import dataclass
@ -19,7 +18,6 @@ import httpx
from agent.auxiliary_client import async_call_llm, extract_content_or_reasoning from agent.auxiliary_client import async_call_llm, extract_content_or_reasoning
from hermes_constants import get_hermes_home from hermes_constants import get_hermes_home
from plugins.teams_pipeline.meetings import ( from plugins.teams_pipeline.meetings import (
TeamsMeetingArtifactNotFoundError,
download_recording_artifact, download_recording_artifact,
enrich_meeting_with_call_record, enrich_meeting_with_call_record,
fetch_preferred_transcript_text, fetch_preferred_transcript_text,

View File

@ -33,26 +33,19 @@ except ModuleNotFoundError:
import asyncio import asyncio
import base64 import base64
import concurrent.futures
import contextvars
import copy import copy
import hashlib import hashlib
import json import json
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
import os import os
import random
import re import re
import ssl
import sys import sys
import tempfile import tempfile
import time import time
import threading import threading
from types import SimpleNamespace
import urllib.request
import uuid import uuid
from typing import List, Dict, Any, Optional 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 # 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 # 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: # 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 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. # `OpenAI` is re-exported here so `patch("run_agent.OpenAI", ...)` in tests works.
from agent.process_bootstrap import ( from agent.process_bootstrap import (
OpenAI,
_OpenAIProxy,
_load_openai_cls,
_SafeWriter,
_install_safe_stdio,
_get_proxy_from_env,
_get_proxy_for_base_url, _get_proxy_for_base_url,
) )
from agent.iteration_budget import IterationBudget from agent.iteration_budget import IterationBudget
@ -102,77 +89,27 @@ else:
# Import our tool system # Import our tool system
from model_tools import ( from model_tools import (
get_tool_definitions,
get_toolset_for_tool, 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 cleanup_vm
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.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
# Agent internals extracted to agent/ package for modularity # Agent internals extracted to agent/ package for modularity
from agent.memory_manager import StreamingContextScrubber, build_memory_context_block, sanitize_context from agent.memory_manager import sanitize_context
from agent.think_scrubber import StreamingThinkScrubber from agent.error_classifier import FailoverReason
from agent.retry_utils import jittered_backoff
from agent.error_classifier import classify_api_error, FailoverReason
from agent.redact import redact_sensitive_text 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 ( from agent.model_metadata import (
fetch_model_metadata, is_local_endpoint,
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,
) )
from agent.context_compressor import ContextCompressor from agent.usage_pricing import normalize_usage
from agent.subdirectory_hints import SubdirectoryHintTracker # Re-exported for tests that monkeypatch these symbols on run_agent.
from agent.prompt_caching import apply_anthropic_cache_control from agent.context_compressor import ContextCompressor # noqa: F401
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.retry_utils import jittered_backoff # noqa: F401
from agent.usage_pricing import estimate_usage_cost, normalize_usage from agent.prompt_builder import build_skills_system_prompt, load_soul_md # noqa: F401
from agent.codex_responses_adapter import ( from agent.process_bootstrap import _get_proxy_from_env # noqa: F401
_derive_responses_function_call_id as _codex_derive_responses_function_call_id, from agent.message_sanitization import ( # noqa: F401
_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 (
_SURROGATE_RE, _SURROGATE_RE,
_sanitize_surrogates, _sanitize_surrogates,
_sanitize_structure_surrogates, _sanitize_structure_surrogates,
@ -185,25 +122,33 @@ from agent.message_sanitization import (
_strip_images_from_messages, _strip_images_from_messages,
_sanitize_structure_non_ascii, _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 ( 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, _should_parallelize_tool_batch,
_extract_parallel_scope_path,
_paths_overlap,
_is_multimodal_tool_result, _is_multimodal_tool_result,
_multimodal_text_summary, _multimodal_text_summary,
_append_subdir_hint_to_multimodal,
_extract_file_mutation_targets, _extract_file_mutation_targets,
_extract_error_preview, _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 utils import atomic_json_write, base_url_host_matches, base_url_hostname
from hermes_cli.config import cfg_get

View File

@ -17,7 +17,6 @@ Usage:
import argparse import argparse
import json import json
import os
import re import re
import subprocess import subprocess
import sys import sys
@ -30,7 +29,7 @@ from pathlib import Path
SCRIPT_DIR = Path(__file__).resolve().parent SCRIPT_DIR = Path(__file__).resolve().parent
sys.path.insert(0, str(SCRIPT_DIR)) 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 REPO_ROOT = SCRIPT_DIR.parent

View File

@ -15,7 +15,6 @@ Usage:
from __future__ import annotations from __future__ import annotations
import argparse import argparse
import json
import sys import sys
from pathlib import Path from pathlib import Path

View File

@ -2,15 +2,11 @@
from __future__ import annotations from __future__ import annotations
from pathlib import Path
import pytest import pytest
from _common import ( from _common import (
DEFAULT_LOCAL_HOST,
EMBEDDING_REGEX, EMBEDDING_REGEX,
FOLDER_ALIASES,
build_cloud_aware_url,
cloud_endpoint, cloud_endpoint,
coerce_seed, coerce_seed,
folder_aliases_for, folder_aliases_for,

View File

@ -2,7 +2,6 @@
from __future__ import annotations from __future__ import annotations
import pytest
from extract_schema import ( from extract_schema import (
extract_schema, extract_schema,

View File

@ -2,10 +2,7 @@
from __future__ import annotations from __future__ import annotations
import copy
import json
import pytest
from extract_schema import extract_schema from extract_schema import extract_schema
from run_workflow import ( from run_workflow import (

View File

@ -18,7 +18,6 @@ Commands:
import argparse import argparse
import json import json
import math import math
import os
import sys import sys
import time import time
import urllib.error import urllib.error

View File

@ -13,11 +13,8 @@ Both fixed together by:
threads don't collide. threads don't collide.
""" """
import os
import threading import threading
from unittest.mock import MagicMock
import pytest
class TestThreadLocalApprovalCallback: class TestThreadLocalApprovalCallback:

View File

@ -9,7 +9,7 @@ from unittest.mock import AsyncMock, MagicMock, patch
import pytest import pytest
import acp import acp
from acp.schema import AgentPlanUpdate, ToolCallStart, ToolCallProgress, AgentThoughtChunk, AgentMessageChunk from acp.schema import AgentPlanUpdate
from acp_adapter.events import ( from acp_adapter.events import (
_build_plan_update_from_todo_result, _build_plan_update_from_todo_result,

View File

@ -7,9 +7,6 @@ Exercises the full flow through the ACP server layer:
session_update events arrive at the mock client 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 from unittest.mock import AsyncMock, MagicMock, patch
import pytest import pytest

View File

@ -18,7 +18,6 @@ from acp.schema import (
AvailableCommandsUpdate, AvailableCommandsUpdate,
Implementation, Implementation,
InitializeResponse, InitializeResponse,
ListSessionsResponse,
LoadSessionResponse, LoadSessionResponse,
NewSessionResponse, NewSessionResponse,
PromptResponse, PromptResponse,
@ -33,7 +32,6 @@ from acp.schema import (
TextContentBlock, TextContentBlock,
ToolCallProgress, ToolCallProgress,
ToolCallStart, ToolCallStart,
Usage,
UsageUpdate, UsageUpdate,
UserMessageChunk, UserMessageChunk,
) )

View File

@ -1,6 +1,5 @@
"""Tests for acp_adapter.tools — tool kind mapping and ACP content building.""" """Tests for acp_adapter.tools — tool kind mapping and ACP content building."""
import pytest
from acp_adapter.edit_approval import EditProposal from acp_adapter.edit_approval import EditProposal
from acp_adapter.tools import ( from acp_adapter.tools import (

View File

@ -8,8 +8,6 @@ syntax check exactly as if LSP were disabled.
""" """
from __future__ import annotations from __future__ import annotations
import os
import sys
from unittest.mock import MagicMock from unittest.mock import MagicMock
import pytest import pytest

View File

@ -14,15 +14,12 @@ This module verifies:
""" """
from __future__ import annotations from __future__ import annotations
import os
import sys
from pathlib import Path from pathlib import Path
from unittest.mock import MagicMock, patch from unittest.mock import patch
import pytest import pytest
from agent.lsp.manager import LSPService from agent.lsp.manager import LSPService
from agent.lsp.servers import SERVERS, ServerContext, ServerDef, SpawnSpec
from agent.lsp.workspace import clear_cache from agent.lsp.workspace import clear_cache

View File

@ -6,12 +6,8 @@ having LSP output prepended to the lint string.
""" """
from __future__ import annotations from __future__ import annotations
import os from unittest.mock import patch
import sys
import tempfile
from unittest.mock import MagicMock, patch
import pytest
from tools.environments.local import LocalEnvironment from tools.environments.local import LocalEnvironment
from tools.file_operations import ( from tools.file_operations import (

View File

@ -7,7 +7,7 @@ pyright/gopls/etc. are still alive on the host.
from __future__ import annotations from __future__ import annotations
import atexit import atexit
from unittest.mock import MagicMock, patch from unittest.mock import MagicMock
import pytest import pytest

View File

@ -2,7 +2,6 @@
from __future__ import annotations from __future__ import annotations
from agent.lsp.reporter import ( from agent.lsp.reporter import (
DEFAULT_SEVERITIES,
MAX_PER_FILE, MAX_PER_FILE,
format_diagnostic, format_diagnostic,
report_for_file, report_for_file,

View File

@ -7,7 +7,6 @@ on.
""" """
from __future__ import annotations from __future__ import annotations
import os
import sys import sys
from pathlib import Path from pathlib import Path
@ -19,7 +18,6 @@ from agent.lsp.servers import (
ServerContext, ServerContext,
ServerDef, ServerDef,
SpawnSpec, SpawnSpec,
find_server_for_file,
) )

View File

@ -1,10 +1,8 @@
"""Tests for Bug #12905 fixes in agent/anthropic_adapter.py — macOS Keychain support.""" """Tests for Bug #12905 fixes in agent/anthropic_adapter.py — macOS Keychain support."""
import json import json
import platform
from unittest.mock import patch, MagicMock from unittest.mock import patch, MagicMock
import pytest
from agent.anthropic_adapter import ( from agent.anthropic_adapter import (
_read_claude_code_credentials_from_keychain, _read_claude_code_credentials_from_keychain,

View File

@ -8,11 +8,9 @@ name in the tool registry.
from __future__ import annotations from __future__ import annotations
import json
from types import SimpleNamespace from types import SimpleNamespace
from unittest.mock import patch from unittest.mock import patch
import pytest
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------

View File

@ -15,7 +15,6 @@ History:
from __future__ import annotations from __future__ import annotations
import io
import json import json
from typing import Any, Dict from typing import Any, Dict
from urllib.parse import parse_qs, urlparse from urllib.parse import parse_qs, urlparse

View File

@ -8,7 +8,6 @@ import warnings
from concurrent.futures import Future from concurrent.futures import Future
from unittest.mock import patch from unittest.mock import patch
import pytest
from agent.async_utils import safe_schedule_threadsafe from agent.async_utils import safe_schedule_threadsafe

View File

@ -2,9 +2,7 @@
import json import json
import logging import logging
import os
import time import time
from pathlib import Path
from types import SimpleNamespace from types import SimpleNamespace
from unittest.mock import patch, MagicMock, AsyncMock from unittest.mock import patch, MagicMock, AsyncMock
@ -609,7 +607,7 @@ class TestExpiredCodexFallback:
monkeypatch.setenv("ANTHROPIC_TOKEN", "sk-ant-oat01-test-fallback") monkeypatch.setenv("ANTHROPIC_TOKEN", "sk-ant-oat01-test-fallback")
with patch("agent.anthropic_adapter.build_anthropic_client") as mock_build: with patch("agent.anthropic_adapter.build_anthropic_client") as mock_build:
mock_build.return_value = MagicMock() mock_build.return_value = MagicMock()
from agent.auxiliary_client import _resolve_auto, AnthropicAuxiliaryClient from agent.auxiliary_client import _resolve_auto
client, model = _resolve_auto() client, model = _resolve_auto()
# Should NOT be Codex, should be Anthropic (or another available provider) # Should NOT be Codex, should be Anthropic (or another available provider)
assert not isinstance(client, type(None)), "Should find a provider after expired Codex" 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.anthropic_adapter.build_anthropic_client") as mock_build, \
patch("agent.auxiliary_client._select_pool_entry", return_value=(False, None)): patch("agent.auxiliary_client._select_pool_entry", return_value=(False, None)):
mock_build.return_value = MagicMock() mock_build.return_value = MagicMock()
from agent.auxiliary_client import _try_anthropic, AnthropicAuxiliaryClient from agent.auxiliary_client import _try_anthropic
client, model = _try_anthropic() client, model = _try_anthropic()
assert client is not None, "Should resolve token" assert client is not None, "Should resolve token"
adapter = client.chat.completions adapter = client.chat.completions
@ -751,7 +749,7 @@ class TestExpiredCodexFallback:
monkeypatch.delenv("ANTHROPIC_TOKEN", raising=False) monkeypatch.delenv("ANTHROPIC_TOKEN", raising=False)
with patch("agent.anthropic_adapter.build_anthropic_client") as mock_build: with patch("agent.anthropic_adapter.build_anthropic_client") as mock_build:
mock_build.return_value = MagicMock() mock_build.return_value = MagicMock()
from agent.auxiliary_client import _try_anthropic, AnthropicAuxiliaryClient from agent.auxiliary_client import _try_anthropic
client, model = _try_anthropic() client, model = _try_anthropic()
assert client is not None assert client is not None
adapter = client.chat.completions adapter = client.chat.completions

View File

@ -27,7 +27,6 @@ from __future__ import annotations
import sys import sys
from types import SimpleNamespace from types import SimpleNamespace
from unittest.mock import MagicMock, patch
import pytest import pytest

View File

@ -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. Also tests the vision_tools and browser_tool model override env vars.
""" """
import json
import os import os
import sys import sys
from pathlib import Path from pathlib import Path
from unittest.mock import patch, MagicMock from unittest.mock import patch, MagicMock
import pytest
import yaml
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..")) sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", ".."))

View File

@ -15,7 +15,6 @@ from __future__ import annotations
from unittest.mock import MagicMock, patch from unittest.mock import MagicMock, patch
import pytest
# ── Text aux tasks — _resolve_auto ────────────────────────────────────────── # ── Text aux tasks — _resolve_auto ──────────────────────────────────────────

View File

@ -1,6 +1,5 @@
"""Tests for named custom provider and 'main' alias resolution in auxiliary_client.""" """Tests for named custom provider and 'main' alias resolution in auxiliary_client."""
import os
from unittest.mock import patch, MagicMock from unittest.mock import patch, MagicMock
import pytest import pytest

View File

@ -23,7 +23,6 @@ import sys
from collections.abc import Callable from collections.abc import Callable
from types import SimpleNamespace from types import SimpleNamespace
from typing import cast from typing import cast
from unittest.mock import MagicMock, patch
import pytest import pytest

View File

@ -10,11 +10,9 @@ Covers:
""" """
import json import json
import os
import time
from contextlib import contextmanager from contextlib import contextmanager
from types import ModuleType, SimpleNamespace from types import ModuleType
from unittest.mock import MagicMock, patch, PropertyMock from unittest.mock import MagicMock, patch
import pytest import pytest
@ -129,7 +127,7 @@ class TestResolveBedrocRegion:
def test_defaults_to_us_east_1(self): def test_defaults_to_us_east_1(self):
from agent.bedrock_adapter import resolve_bedrock_region from agent.bedrock_adapter import resolve_bedrock_region
from unittest.mock import patch, MagicMock from unittest.mock import MagicMock
mock_session = MagicMock() mock_session = MagicMock()
mock_session.get_config_variable.return_value = None mock_session.get_config_variable.return_value = None
with _mock_botocore_session(return_value=mock_session): with _mock_botocore_session(return_value=mock_session):
@ -137,7 +135,7 @@ class TestResolveBedrocRegion:
def test_falls_back_to_botocore_profile_region(self): def test_falls_back_to_botocore_profile_region(self):
from agent.bedrock_adapter import resolve_bedrock_region from agent.bedrock_adapter import resolve_bedrock_region
from unittest.mock import patch, MagicMock from unittest.mock import MagicMock
mock_session = MagicMock() mock_session = MagicMock()
mock_session.get_config_variable.return_value = "eu-central-1" mock_session.get_config_variable.return_value = "eu-central-1"
with _mock_botocore_session(return_value=mock_session): 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): def test_botocore_failure_falls_back_to_us_east_1(self):
from agent.bedrock_adapter import resolve_bedrock_region from agent.bedrock_adapter import resolve_bedrock_region
from unittest.mock import patch
with _mock_botocore_session(side_effect=Exception("no botocore")): with _mock_botocore_session(side_effect=Exception("no botocore")):
assert resolve_bedrock_region({}) == "us-east-1" assert resolve_bedrock_region({}) == "us-east-1"

View File

@ -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. require Python 3.10+ due to ``str | None`` type syntax in the import chain.
""" """
import os
from unittest.mock import MagicMock, patch from unittest.mock import MagicMock, patch
import pytest import pytest
@ -93,7 +92,6 @@ class TestResolveProvider:
def test_explicit_bedrock_resolves(self, monkeypatch): def test_explicit_bedrock_resolves(self, monkeypatch):
"""When user explicitly requests 'bedrock', it should resolve.""" """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 # bedrock is in the registry, so resolve_provider should return it
from hermes_cli.auth import resolve_provider from hermes_cli.auth import resolve_provider
result = resolve_provider("bedrock") result = resolve_provider("bedrock")

View File

@ -29,7 +29,6 @@ import base64
import json import json
from unittest.mock import MagicMock, patch from unittest.mock import MagicMock, patch
import pytest
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------

View File

@ -8,7 +8,6 @@ creative workflows that iterate on images across many turns.
from __future__ import annotations from __future__ import annotations
import pytest
from agent.context_compressor import ( from agent.context_compressor import (
_CHARS_PER_TOKEN, _CHARS_PER_TOKEN,

View File

@ -232,7 +232,7 @@ class TestPluginContextEngineSlot:
assert mgr._context_engine is None assert mgr._context_engine is None
def test_get_plugin_context_engine(self): 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 import hermes_cli.plugins as plugins_mod
# Inject a test manager # Inject a test manager

View File

@ -28,7 +28,6 @@ from __future__ import annotations
from unittest.mock import MagicMock from unittest.mock import MagicMock
import pytest
from run_agent import AIAgent from run_agent import AIAgent

View File

@ -10,9 +10,7 @@ so it can run without optional dependencies like firecrawl.
import asyncio import asyncio
import threading import threading
from concurrent.futures import ThreadPoolExecutor
from unittest.mock import patch, MagicMock from unittest.mock import patch, MagicMock
from types import SimpleNamespace
import pytest import pytest
@ -32,7 +30,6 @@ def _stub_resolve_provider_client(provider, model, async_mode, **kw):
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def _clean_client_cache(): def _clean_client_cache():
"""Clear the client cache before each test.""" """Clear the client cache before each test."""
import importlib
# We need to patch before importing # We need to patch before importing
with patch.dict("sys.modules", {}): with patch.dict("sys.modules", {}):
pass pass
@ -48,7 +45,7 @@ class TestCrossLoopCacheIsolation:
def test_same_loop_reuses_client(self): def test_same_loop_reuses_client(self):
"""Within a single event loop, the same client should be returned.""" """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() loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop) asyncio.set_event_loop(loop)

View File

@ -7,7 +7,6 @@ tests run fully offline and the curator module doesn't need real credentials.
from __future__ import annotations from __future__ import annotations
import importlib import importlib
import json
from datetime import datetime, timedelta, timezone from datetime import datetime, timedelta, timezone
from pathlib import Path from pathlib import Path

View File

@ -7,8 +7,7 @@ the standard log dir, not inside the user's ``skills/`` data directory.
from __future__ import annotations from __future__ import annotations
import json import json
import os from datetime import datetime, timezone
from datetime import datetime, timezone, timedelta
from pathlib import Path from pathlib import Path
import pytest import pytest

View File

@ -1,9 +1,8 @@
"""Tests for agent/display.py — build_tool_preview() and inline diff previews.""" """Tests for agent/display.py — build_tool_preview() and inline diff previews."""
import os
import json import json
import pytest import pytest
from unittest.mock import MagicMock, patch from unittest.mock import MagicMock
from agent.display import ( from agent.display import (
build_tool_preview, build_tool_preview,

View File

@ -5,7 +5,6 @@ todo tool call paths: read, create (merge=False), update (merge=True).
""" """
import json import json
import pytest
from agent.display import get_cute_tool_message from agent.display import get_cute_tool_message

View File

@ -7,7 +7,6 @@ not a generic "[error]".
""" """
import json import json
import pytest
from agent.display import ( from agent.display import (
_detect_tool_failure, _detect_tool_failure,

Some files were not shown because too many files have changed in this diff Show More