mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-24 16:54:43 +00:00
Review on #20379, finding 1 (High). Two ways an MCP config revision could be silently acknowledged without ever being applied: Client: the poll advanced its accepted mcp_rev BEFORE calling reload.mcp, and quietRpc collapses failures to null — a reload that failed against a temporarily broken server left the revision recorded as applied, and no subsequent poll retried until an unrelated MCP edit. The handshake is now syncMcpReload(): send the observed rev with the request, advance `accepted` only when the server answers status=reloaded (to the server's loaded_rev, falling back to the requested rev on older gateways), and re-compare on EVERY poll tick — decoupled from mtime — so a transient failure heals on the next tick. An in-flight guard stops the 5s poll from stacking requests behind a slow reload. Server: generation-only coalescing let a follower triggered by revision B ack against revision A's registry when the config changed under a slow leader. The leader now re-hashes the MCP-relevant config after discovery and repeats until stable (bounded), records _mcp_reload_loaded_rev, and a follower coalesces only when the revision it was asked to load matches — otherwise it re-runs the full reload itself. Responses carry loaded_rev. Deterministic tests for the exact failure sequences: failed reload → no ack, no generation advance; A-then-B overlap → follower re-runs; matching rev → coalesces; failed leader → follower re-runs; legacy no-rev callers keep generation-only coalescing (thread ordering via an instrumented lock, no sleeps). Client: 6 vitest cases on the ack/retry/in-flight contract. |
||
|---|---|---|
| .. | ||
| __init__.py | ||
| test_billing_rpc.py | ||
| test_codex_app_server_live_events.py | ||
| test_compaction_status.py | ||
| test_compute_host.py | ||
| test_compute_host_phase1.py | ||
| test_custom_provider_session_persistence.py | ||
| test_delegation_session_lifecycle.py | ||
| test_entry_sys_path.py | ||
| test_fast_session_scope.py | ||
| test_finalize_session_persist.py | ||
| test_gateway_owned_session_reap.py | ||
| test_goal_command.py | ||
| test_image_routing_stale_model.py | ||
| test_inline_rpc_gil_starvation.py | ||
| test_interim_assistant_callback.py | ||
| test_iso_certify_seam.py | ||
| test_make_agent_provider.py | ||
| test_mcp_late_refresh_thread_owner.py | ||
| test_mcp_reload_rev.py | ||
| test_moa_reference_emit.py | ||
| test_model_switch_marker_role.py | ||
| test_pet_generate_rpc.py | ||
| test_project_tree.py | ||
| test_projects_rpc.py | ||
| test_protocol.py | ||
| test_reasoning_config_per_model.py | ||
| test_reasoning_session_scope.py | ||
| test_render.py | ||
| test_review_summary_callback.py | ||
| test_session_platform_resolution.py | ||
| test_slash_worker_ansi.py | ||
| test_slash_worker_mcp_discovery.py | ||
| test_slash_worker_profile_home.py | ||
| test_slash_worker_sys_path.py | ||
| test_subagent_child_mirror.py | ||
| test_undo_command.py | ||
| test_wait_for_mcp_discovery.py | ||