* refactor(plugins): remove the Sep 2026 decomposition compat layer on schedule The PLUGIN-COMPAT layer (2776813df3+d63e380324+0a5164cebe) kept pre-#102117 import paths alive for external plugins until 2026-09-14. That window closed two weeks ago; since then the loader has already been skipping plugins that use the old paths. This removes the layer itself: - 328 appended `PLUGIN-COMPAT` blocks (lazy `__getattr__` pointer tables, re-exported third-party names, restored dead definitions) and the three re-export stub modules (gateway/startup_watchdog, hermes_cli/observability/relay_runtime, tools/environments/modal_utils) - COMPAT_MANIFEST.md, compat_manifest.json, scripts/check_compat_pointers.py and its lint step - the reporting surfaces: CLI banner notice, `hermes plugins compat`, the `hermes doctor` section, the post-update notice, the Desktop one-time dialog, the loader's pre-import skip and the `plugins.allow_deprecated_imports` escape hatch An external plugin that still imports an old path now fails to load with its ImportError as the reason in `hermes plugins list`, the same path as any broken plugin. hermes_cli/plugin_compat.py stays as three inert stubs (compat_report, removal_in_effect, summary_lines): an already-running pre-removal `hermes update` lazy-imports them after the checkout swap (tests/compat/old_updater_surface.json). In-tree fallout, both already dead: hermes_cli/setup.py::_check_espeak_ng (no callers; its `shutil` came from a compat block) and gateway/config.py::SessionResetPolicy ("retained solely for the scheduled plugin-compat window"). Two test_run_agent patches targeted the removed `run_agent.handle_function_call` pointer; they now patch `model_tools.handle_function_call`, the seam production reads, like every sibling test in that file. * chore: retrigger CI (zero-job startup_failure phantom) * test: drop resolution allowlist rows for the two deleted which() sites hermes_cli/setup.py::_check_espeak_ng (dead) and tools/skillevaluator_scan.py::scanner_available (a restored definition inside a PLUGIN-COMPAT block) no longer exist; the stale-row gate requires their allowlist entries go with them.
59 lines
2.8 KiB
Python
59 lines
2.8 KiB
Python
"""Per-attempt recovery bookkeeping (``TurnRetryState``) for the conversation turn loop.
|
|
Dependency-free so it imports without a cycle."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
|
|
|
|
@dataclass
|
|
class TurnRetryState:
|
|
"""One-shot recovery guards + restart signals for a single API-call attempt.
|
|
|
|
A fresh instance is created per ``api_call_count`` iteration; each guard fires at
|
|
most once, and ``restart_with_*`` signals tell the loop to rebuild and retry.
|
|
Loop-control (``retry_count``, ``max_retries``) stays as plain loop locals."""
|
|
|
|
# Per-provider OAuth / credential refresh guards
|
|
codex_auth_retry_attempted: bool = False
|
|
anthropic_auth_retry_attempted: bool = False
|
|
nous_auth_retry_attempted: bool = False
|
|
nous_paid_entitlement_refresh_attempted: bool = False
|
|
# Nous free tier: one model move onto the tier's own model after a ``model_not_free``
|
|
# refusal, and one route re-read after a wrong-host refusal (``anon_on_paid_host``).
|
|
welcome_model_switch_attempted: bool = False
|
|
welcome_route_heal_attempted: bool = False
|
|
copilot_auth_retry_attempted: bool = False
|
|
# Copilot surfaces a stale credential as a 400 ``model_not_available_for_integrator``
|
|
# / ``model_not_supported``, not a 401 — separate guard from the 401 one.
|
|
copilot_stale_cred_retry_attempted: bool = False
|
|
vertex_auth_retry_attempted: bool = False
|
|
|
|
# Format / payload recovery guards
|
|
thinking_sig_retry_attempted: bool = False
|
|
invalid_encrypted_content_retry_attempted: bool = False
|
|
native_compaction_reject_retry_attempted: bool = False
|
|
image_shrink_retry_attempted: bool = False
|
|
multimodal_tool_content_retry_attempted: bool = False
|
|
reasoning_mandatory_retry_attempted: bool = False
|
|
oauth_1m_beta_retry_attempted: bool = False
|
|
llama_cpp_grammar_retry_attempted: bool = False
|
|
|
|
# Transport / rate-limit recovery
|
|
primary_recovery_attempted: bool = False
|
|
has_retried_429: bool = False
|
|
# Persistent 401/403 already escalated to the fallback chain once this attempt.
|
|
auth_failover_attempted: bool = False
|
|
# Post-exhaustion auto-recovery cycles spent on this API call (agent.auto_recovery_cycles caps it).
|
|
auto_recovery_cycles_used: int = 0
|
|
|
|
# Restart signals (read by the outer loop after the attempt)
|
|
restart_with_compressed_messages: bool = False
|
|
restart_with_length_continuation: bool = False
|
|
# A fallback activation (incl. content-filter stream stalls) rolled partial content
|
|
# off ``messages``; re-issue the call against the new provider.
|
|
restart_with_rebuilt_messages: bool = False
|
|
# A user correction cancelled the in-flight request: append a role-safe checkpoint +
|
|
# user message, rebuild the payload, and retry the same logical iteration.
|
|
restart_with_redirected_messages: bool = False
|