hermes-agent/agent
Ian Culling 86e10dd874 fix(agent): route 'thinking blocks cannot be modified' 400 to recovery
Anthropic returns a 400 when the thinking/redacted_thinking blocks in the
latest assistant message are mutated upstream: 'thinking or redacted_thinking
blocks in the latest assistant message cannot be modified. These blocks must
remain as they were in the original response.'

The classifier's thinking_signature branch only matched on the substring
'signature', so this variant fell through to a non-retryable client error
and hard-aborted the turn -- even though the existing strip-reasoning_details
-and-retry recovery would have healed it.

Broaden the 400 match to also catch 'cannot be modified' / 'must remain as
they were' (still gated on 'thinking'), routing it to the same recovery.
Adds a negative-case test so unrelated 'cannot be modified' 400s are not
swept in.

Defense-in-depth, orthogonal to the root-cause work in #35975 / #17861
(which prevent the block mutation in the first place). Only changes a
terminal-failure into a one-shot recovery.

Signed-off-by: Ian Culling <ian@culling.ca>
2026-06-10 12:39:44 -07:00
..
lsp fix: prevent TUI gateway stdin EOF crash across all TUI-context subprocess calls 2026-06-08 22:46:57 -07:00
secret_sources fix: prevent TUI gateway stdin EOF crash across all TUI-context subprocess calls 2026-06-08 22:46:57 -07:00
transports fix(codex): record app-server token usage in session accounting 2026-06-09 02:46:04 -07:00
__init__.py
…
account_usage.py feat(credits): usage-aware credits — in-session notices, /usage view, dev readout (#40011) 2026-06-06 13:18:18 +05:30
agent_init.py feat(desktop): resizable VS Code-themed terminal pane + palette polish (#42521) 2026-06-09 23:15:20 -05:00
agent_runtime_helpers.py feat(desktop): resizable VS Code-themed terminal pane + palette polish (#42521) 2026-06-09 23:15:20 -05:00
anthropic_adapter.py fix(anthropic): default new Claude models to the modern thinking contract (#42991) 2026-06-09 23:37:23 +05:30
async_utils.py
…
auxiliary_client.py fix(params): send max_completion_tokens for newer OpenAI families on custom endpoints 2026-06-09 23:22:10 -07:00
azure_identity_adapter.py
…
background_review.py fix(compression): disable compression on background-review fork to prevent cross-turn stale-parent fork (#41708) 2026-06-07 22:06:48 -07:00
bedrock_adapter.py
…
browser_provider.py
…
browser_registry.py
…
chat_completion_helpers.py fix(stream): don't report dropped mid-tool-call streams as output truncation (#42314) 2026-06-08 11:56:10 -07:00
codex_responses_adapter.py
…
codex_runtime.py fix(codex): record app-server token usage in session accounting 2026-06-09 02:46:04 -07:00
context_compressor.py fix(compression): clear _previous_summary on session end (defense-in-depth) 2026-06-07 22:09:45 -07:00
context_engine.py
…
context_references.py fix(agent): make a binary @file: reference actionable instead of a dead end 2026-06-09 19:16:46 -05:00
conversation_compression.py test(gateway): add compression session_id rotation integration tests (#34089) 2026-06-07 22:39:51 -07:00
conversation_loop.py refactor(agent): extract run_conversation post-loop tail into finalize_turn (god-file Phase 1) 2026-06-08 09:42:23 -07:00
copilot_acp_client.py
…
credential_persistence.py
…
credential_pool.py fix(auth): add Codex OAuth accounts as distinct pool entries 2026-06-08 11:57:03 -07:00
credential_sources.py
…
credits_tracker.py Suppress "Credit access paused" notice on free models (#43669) 2026-06-10 23:55:06 +05:30
curator.py fix(curator): use shared atomic state writer 2026-06-10 03:04:54 -07:00
curator_backup.py
…
display.py
…
error_classifier.py fix(agent): route 'thinking blocks cannot be modified' 400 to recovery 2026-06-10 12:39:44 -07:00
file_safety.py
…
gemini_cloudcode_adapter.py
…
gemini_native_adapter.py fix(gemini): default native maxOutputTokens + strip OpenAI extra_body on Gemini endpoints (#39730) 2026-06-05 03:53:59 -07:00
gemini_schema.py
…
google_code_assist.py
…
google_oauth.py
…
i18n.py fix(packaging): ship locales/ i18n catalogs in wheel, sdist, and Nix (#38383) 2026-06-03 12:00:27 -07:00
image_gen_provider.py
…
image_gen_registry.py
…
image_routing.py fix(vision): honor custom_providers per-model supports_vision (#41036) 2026-06-07 21:50:57 -07:00
insights.py refactor(insights): drop dead pricing/duration wrappers, call usage_pricing directly (#40618) 2026-06-07 18:33:20 -07:00
iteration_budget.py
…
jiter_preload.py
…
lmstudio_reasoning.py
…
manual_compression_feedback.py
…
markdown_tables.py
…
memory_manager.py fix(memory): run end-of-turn sync off the turn thread (#41945) 2026-06-08 02:18:59 -07:00
memory_provider.py
…
message_sanitization.py
…
model_metadata.py fix(model_metadata): prefer hardcoded 1M for MiniMax M3 over stale models.dev probe 2026-06-09 23:24:40 -07:00
models_dev.py
…
moonshot_schema.py
…
nous_rate_guard.py
…
onboarding.py feat(onboarding): opt-in structured profile-build path on first contact (#41114) 2026-06-07 08:36:48 -07:00
plugin_llm.py
…
portal_tags.py
…
process_bootstrap.py
…
prompt_builder.py feat(desktop): resizable VS Code-themed terminal pane + palette polish (#42521) 2026-06-09 23:15:20 -05:00
prompt_caching.py
…
rate_limit_tracker.py
…
redact.py
…
retry_utils.py
…
runtime_cwd.py fix(desktop): stabilize project folder sessions (#37586) 2026-06-02 20:23:09 +00:00
shell_hooks.py
…
skill_bundles.py
…
skill_commands.py refactor(skills): clean up bundled skill set + add environments: relevance gate (#39028) 2026-06-04 06:11:22 -07:00
skill_preprocessing.py fix: prevent TUI gateway stdin EOF crash across all TUI-context subprocess calls 2026-06-08 22:46:57 -07:00
skill_utils.py refactor(skills): clean up bundled skill set + add environments: relevance gate (#39028) 2026-06-04 06:11:22 -07:00
stream_diag.py
…
subdirectory_hints.py
…
system_prompt.py fix(agent): make mid-turn /steer trusted, not read as injection 2026-06-05 20:59:36 -05:00
think_scrubber.py
…
title_generator.py
…
tool_dispatch_helpers.py
…
tool_executor.py feat(desktop): resizable VS Code-themed terminal pane + palette polish (#42521) 2026-06-09 23:15:20 -05:00
tool_guardrails.py
…
tool_result_classification.py
…
trajectory.py
…
transcription_provider.py
…
transcription_registry.py
…
tts_provider.py
…
tts_registry.py
…
turn_context.py refactor(agent): extract run_conversation prologue into agent/turn_context.py 2026-06-07 22:17:35 -07:00
turn_finalizer.py refactor(agent): extract run_conversation post-loop tail into finalize_turn (god-file Phase 1) 2026-06-08 09:42:23 -07:00
turn_retry_state.py refactor(agent): consolidate inner-retry-loop recovery flags into TurnRetryState (god-file Phase 1b) 2026-06-07 22:42:05 -07:00
usage_pricing.py fix(model): require confirmation for expensive model selections 2026-06-10 00:24:06 -07:00
video_gen_provider.py
…
video_gen_registry.py
…
web_search_provider.py
…
web_search_registry.py
…