hermes-bsd/agent
DavidMetcalfe 865a09a610 fix(agent): detect thinking-timeout for reasoning models and surface actionable guidance instead of misleading file-write advice
Two-part fix:

Part 1 (classifier override at agent/error_classifier.py:720-738):
A transport disconnect on a reasoning model — even on a large session —
now routes to FailoverReason.timeout instead of context_overflow. Without
this, large-session reasoning-model disconnects route to the compression
branch and silently delete conversation history on a phantom
context-length error. The override is strictly targeted: non-reasoning
models (gpt-4o, claude-3-5-sonnet, llama-3.3-70b, etc.) still route to
context_overflow on large sessions — the existing intentional behavior
for chat models whose proxy doesn't idle-kill during prefill/generation.

Part 2 (new agent/thinking_timeout_guidance.py + integration at
agent/conversation_loop.py:3488-3567):
New is_thinking_timeout() and build_thinking_timeout_guidance() helpers.
When a known reasoning model (NVIDIA Nemotron 3 Ultra, OpenAI o1/o3,
Anthropic Opus 4.x thinking, DeepSeek R1, Qwen QwQ, xAI Grok reasoning)
hits a transport-kill on a small session (classifier says timeout
directly) or after Part 1 routes correctly (large session), the user
now sees reasoning-specific guidance with three actionable workarounds
in priority order:

  1. Set providers.<provider>.models.<model>.stale_timeout_seconds: 900
     in ~/.hermes/config.yaml (Hermes's built-in floor is already 600s
     for known reasoning models; raise further if upstream is even
     tighter).
  2. Lower reasoning_budget or set reasoning_effort: medium on this
     model if the provider supports it.
  3. Use a smaller / faster reasoning model if the task doesn't
     require deep thinking.

The new guidance takes precedence via if/elif over the existing
_is_stream_drop block, so a reasoning-model user with a transport-kill
message sees actionable advice instead of the misleading "try
execute_code with Python's open() for large files" advice (which is
correct for the unrelated large-file-write stream-drop case but
actively wrong for the thinking-timeout case).

Verified:
- 478 tests passing across 9 directly-relevant files (49 new + 429
  existing, zero regressions).
- Ruff lint clean on all 4 modified/new files.
- Negative test: 6 parametrized regression guards confirm non-reasoning
  models still route to context_overflow on large sessions; 4
  parametrized gates confirm non-timeout classifier reasons never
  trigger the guidance; 5 parametrized cases confirm non-transport
  messages never trigger it.
- Regression guard: new guidance message does NOT contain
  "execute_code" or "open()" — the misleading advice is fully
  replaced, not appended alongside.
- Cross-vendor dual review via agy -p:
  - Gemini 3.5 Flash (Medium) — passed: true, zero blockers, one
    SHOULD-FIX (vprint block duplication — fixed by extracting
    detection into a helper module).
  - GPT-OSS 120B (Medium) — passed: true, zero blockers, two nits
    (test placement — adopted at tests/agent/test_thinking_timeout_guidance.py;
    primary-model capture — accepted as non-issue per Flash's nit).

Dependency note for maintainers:
This PR includes agent/reasoning_timeouts.py (the reasoning-model
allowlist module from PR #52238) because the Layer 1 override is
load-bearing on get_reasoning_stale_timeout_floor(). After PR #52238
lands on main, this PR's duplicate agent/reasoning_timeouts.py should
be rebased away. Either PR can land first; the other rebase is
mechanical.

Fixes #52271.
2026-06-25 19:00:48 -07:00
..
lsp
pet feat(pets): quality-first OpenRouter model chain + stronger atlas gates + global pet-gen notifications 2026-06-24 23:11:21 -05:00
secret_sources
transports fix(cache): content-address prompt_cache_key so recurring cron jobs reuse the warm prefix (#52295) 2026-06-24 21:46:30 -07:00
__init__.py
account_usage.py
agent_init.py feat(moa): expose MoA presets as selectable virtual models (#46081) 2026-06-25 13:52:06 -07:00
agent_runtime_helpers.py fix(hermes_state): persist billing provider/base_url after mid-session /model switch 2026-06-25 14:44:00 -07:00
anthropic_adapter.py fix(anthropic): use platform.claude.com for OAuth token exchange 2026-06-23 23:59:40 -07:00
async_utils.py
auxiliary_client.py fix(auxiliary): fall back when a route can't run the model at all (400 capability mismatch) 2026-06-25 13:08:18 -07:00
azure_identity_adapter.py
background_review.py feat(background-review): aux-model selector for the self-improvement review (#49252) 2026-06-22 14:54:53 -07:00
bedrock_adapter.py
billing_view.py feat(billing): /billing terminal billing — interactive TUI + CLI client (#45449) 2026-06-19 01:53:32 +05:30
browser_provider.py
browser_registry.py
chat_completion_helpers.py fix(agent): keep system-prompt model identity in sync across provider failover 2026-06-20 10:46:01 -07:00
codex_responses_adapter.py fix(xai): OAuth Responses native web_search, incomplete guard, grok-composer context 2026-06-17 17:33:32 -07:00
codex_runtime.py fix(codex): seed app-server sessions with configured cwd 2026-06-21 16:39:02 -07:00
coding_context.py fix(agent): require code for coding posture 2026-06-25 16:40:27 -05:00
context_compressor.py fix(compression): abort (preserve context) on transient network summary failure (#29559, #25585) 2026-06-24 18:31:51 +05:30
context_engine.py
context_references.py
conversation_compression.py fix(auxiliary): honor fallback chain when compression provider auth is unavailable 2026-06-25 13:08:18 -07:00
conversation_loop.py fix(agent): detect thinking-timeout for reasoning models and surface actionable guidance instead of misleading file-write advice 2026-06-25 19:00:48 -07:00
copilot_acp_client.py
credential_persistence.py
credential_pool.py fix(auth): make load_pool() non-destructive for env-seeded credentials 2026-06-21 08:26:37 -07:00
credential_sources.py
credits_tracker.py
curator.py feat(curator): make skill consolidation opt-in (prune stays default-on) (#47840) 2026-06-17 05:20:32 -07:00
curator_backup.py fix(curator): stop the rollback safety snapshot from pruning its target 2026-06-17 05:40:05 -07:00
display.py feat(moa): expose MoA presets as selectable virtual models (#46081) 2026-06-25 13:52:06 -07:00
error_classifier.py fix(agent): detect thinking-timeout for reasoning models and surface actionable guidance instead of misleading file-write advice 2026-06-25 19:00:48 -07:00
errors.py
file_safety.py
gemini_native_adapter.py
gemini_schema.py
i18n.py
image_gen_provider.py feat(image-gen): add image-to-image / editing to image_generate (#48705) 2026-06-18 22:13:07 -07:00
image_gen_registry.py
image_routing.py
insights.py
iteration_budget.py
jiter_preload.py
learn_prompt.py fix(learn): name distilled skills as author Hermes, not the host OS user (#52388) 2026-06-25 12:48:08 -07:00
lmstudio_reasoning.py
manual_compression_feedback.py
markdown_tables.py
memory_manager.py fix(agent): validate context/memory tool schemas before wrapping 2026-06-25 02:17:29 +05:30
memory_provider.py fix(backup): capture memory-provider state stored outside HERMES_HOME (#50325) 2026-06-21 12:03:46 -07:00
message_content.py fix(openviking): preserve structured sync attribution 2026-06-19 15:23:41 +08:00
message_sanitization.py fix(agent): close tool-call sequence on all interrupt aborts, not just finalize_turn 2026-06-25 12:24:34 -05:00
moa_loop.py feat(moa): expose MoA presets as selectable virtual models (#46081) 2026-06-25 13:52:06 -07:00
model_metadata.py fix(xai): scope native web_search to swap-only + reconcile composer ctx to 200k 2026-06-17 17:33:32 -07:00
models_dev.py
moonshot_schema.py
nous_rate_guard.py
onboarding.py
oneshot.py feat(agent): one-shot LLM helper + llm.oneshot gateway RPC (#51261) 2026-06-23 08:01:50 +00:00
plugin_llm.py
portal_tags.py
process_bootstrap.py
prompt_builder.py feat(tools): add project workspace tools 2026-06-25 16:40:27 -05:00
prompt_caching.py
rate_limit_tracker.py
reasoning_timeouts.py fix(agent): detect thinking-timeout for reasoning models and surface actionable guidance instead of misleading file-write advice 2026-06-25 19:00:48 -07:00
redact.py fix(redact): mask all Authorization schemes and x-api-key style headers 2026-06-21 14:08:06 -07:00
retry_utils.py fix: handle named custom providers and Z.AI overload retries 2026-06-25 00:17:17 -07:00
runtime_cwd.py
secret_scope.py feat(gateway): multiplex phase 2 — fail-closed profile credential isolation (Workstream A) 2026-06-19 07:34:15 -07:00
shell_hooks.py docs: document per-event extra keys in shell-hook wire protocol 2026-06-20 23:23:47 -07:00
skill_bundles.py
skill_commands.py fix(memory): strip skill scaffolding for all providers, not just openviking 2026-06-16 10:37:37 -07:00
skill_preprocessing.py
skill_utils.py refactor(kanban): fold worker/orchestrator skills into injected guidance (#50473) 2026-06-21 17:06:48 -07:00
ssl_guard.py
stream_diag.py
subdirectory_hints.py
system_prompt.py feat(computer_use): cross-platform cua-driver (macOS/Windows/Linux) 2026-06-22 06:42:30 -07:00
think_scrubber.py
thinking_timeout_guidance.py fix(agent): detect thinking-timeout for reasoning models and surface actionable guidance instead of misleading file-write advice 2026-06-25 19:00:48 -07:00
title_generator.py feat(titles): support language-aware title generation (#45296) 2026-06-19 17:15:52 -07:00
tool_dispatch_helpers.py feat(agent): require verification before finishing edits 2026-06-24 23:02:48 -05:00
tool_executor.py fix(agent): handle concurrent tool submit shutdown 2026-06-24 02:56:56 +05:30
tool_guardrails.py
tool_result_classification.py
trajectory.py
transcription_provider.py
transcription_registry.py
tts_provider.py
tts_registry.py
turn_context.py fix: persist non-NULL system prompt on fresh turn setup (#45499) (#52616) 2026-06-25 12:54:19 -07:00
turn_finalizer.py fix(agent): close tool-call sequence on all interrupt aborts, not just finalize_turn 2026-06-25 12:24:34 -05:00
turn_retry_state.py fix(agent): fail over to fallback provider on persistent auth failure (401/403) 2026-06-20 11:38:01 -07:00
usage_pricing.py fix(bedrock): price Claude prompt-cache tokens in /usage (#50307) 2026-06-21 11:48:43 -07:00
verification_evidence.py feat(agent): recognize focused ad-hoc verification scripts 2026-06-24 23:03:45 -05:00
verification_stop.py feat(agent): recognize focused ad-hoc verification scripts 2026-06-24 23:03:45 -05:00
video_gen_provider.py
video_gen_registry.py
web_search_provider.py
web_search_registry.py