mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-26 01:01:40 +00:00
When models return empty responses (no content, no tool calls, no reasoning), Hermes previously retried 3 times silently then fell through to '(empty)' — without ever trying the fallback provider chain. Users on GLM-4.5-Air and similar models experienced what appeared to be a complete hang, especially in gateway (Telegram/Discord) contexts where the silent retries produced zero feedback. Changes: - After exhausting 3 empty retries, attempt _try_activate_fallback() before giving up with '(empty)'. If fallback succeeds, reset retry counter and continue the conversation loop with the new provider. - Replace all _vprint() calls in recovery paths with _emit_status(), which surfaces messages through both CLI (_vprint with force=True) and gateway (status_callback -> adapter.send). Users now see: * '⚠️ Empty response from model — retrying (N/3)' during retries * '⚠️ Model returning empty responses — switching to fallback...' * '↻ Switched to fallback: <model> (<provider>)' on success * '❌ Model returned no content after all retries [and fallback]' - Add logger.warning() throughout empty response paths for log file visibility (model name, provider, retry counts). - Upgrade _last_content_with_tools fallback from logger.debug to logger.info + _emit_status so recovery is visible. - Upgrade thinking-only prefill continuation to use _emit_status. Tests: - test_empty_response_triggers_fallback_provider: verifies fallback activation after 3 empty retries produces content from fallback model - test_empty_response_fallback_also_empty_returns_empty: verifies graceful degradation when fallback also returns empty - test_empty_response_emits_status_for_gateway: verifies _emit_status is called during retries so gateway users see feedback Addresses #7180. |
||
|---|---|---|
| .. | ||
| __init__.py | ||
| test_413_compression.py | ||
| test_860_dedup.py | ||
| test_1630_context_overflow_loop.py | ||
| test_agent_guardrails.py | ||
| test_agent_loop.py | ||
| test_agent_loop_tool_calling.py | ||
| test_agent_loop_vllm.py | ||
| test_anthropic_error_handling.py | ||
| test_async_httpx_del_neuter.py | ||
| test_compression_boundary.py | ||
| test_compression_persistence.py | ||
| test_compressor_fallback_update.py | ||
| test_context_pressure.py | ||
| test_context_token_tracking.py | ||
| test_dict_tool_call_args.py | ||
| test_exit_cleanup_interrupt.py | ||
| test_fallback_model.py | ||
| test_flush_memories_codex.py | ||
| test_interactive_interrupt.py | ||
| test_interrupt_propagation.py | ||
| test_long_context_tier_429.py | ||
| test_openai_client_lifecycle.py | ||
| test_percentage_clamp.py | ||
| test_primary_runtime_restore.py | ||
| test_provider_fallback.py | ||
| test_provider_parity.py | ||
| test_real_interrupt_subagent.py | ||
| test_redirect_stdout_issue.py | ||
| test_run_agent.py | ||
| test_run_agent_codex_responses.py | ||
| test_session_meta_filtering.py | ||
| test_session_reset_fix.py | ||
| test_streaming.py | ||
| test_strict_api_validation.py | ||
| test_switch_model_context.py | ||
| test_token_persistence_non_cli.py | ||
| test_tool_arg_coercion.py | ||
| test_unicode_ascii_codec.py | ||