hermes-agent-features/tests/gateway
Teknium 9b55365f6f
fix(gateway,cron): close ephemeral agents + reap stale aux clients (salvage #13979) (#16598)
* fix: clean gateway auxiliary client caches on teardown

* fix(gateway): recover from stale pid files and close cron agents

Two issues were keeping the gateway from surviving long runs:

1. `_cleanup_invalid_pid_path` delegated to `remove_pid_file`, which
   refuses to unlink when the file's pid differs from our own. That
   safety check exists for the --replace atexit handoff, but it also
   applied to stale-record cleanup, so after a crashy exit the pid
   file was orphaned: `write_pid_file()`'s O_EXCL create then failed
   with `FileExistsError`, and systemd looped on "PID file race lost
   to another gateway instance". Unlink unconditionally from this
   helper since the caller has already verified the record is dead.

2. The cron scheduler never closed the ephemeral `AIAgent` it creates
   per tick, and never swept the process-global auxiliary-client
   cache. Over days of 10-minute ticks this leaked subprocesses and
   async httpx transports until the gateway hit EMFILE. Release the
   agent and call `cleanup_stale_async_clients()` in `run_job`'s
   outer `finally`, matching the gateway's own per-turn cleanup.

* chore(release): map bloodcarter@gmail.com -> bloodcarter

---------

Co-authored-by: bloodcarter <bloodcarter@gmail.com>
2026-04-27 07:41:42 -07:00
..
__init__.py
conftest.py test(gateway): unify discord mock via shared conftest; drop duplicated mock in model_picker test 2026-04-24 03:33:29 -07:00
restart_test_helpers.py fix(gateway): use persisted session origin for shutdown notifications 2026-04-20 05:15:54 -07:00
test_agent_cache.py fixup! fix(gateway): preserve inactivity clock on interrupt-recursive cached-agent turns (#15654) 2026-04-26 08:45:44 -07:00
test_allowlist_startup_check.py
test_api_server_bind_guard.py
test_api_server_jobs.py refactor: remove redundant local imports already available at module level 2026-04-21 00:50:58 -07:00
test_api_server_multimodal.py feat(api-server): inline image inputs on /v1/chat/completions and /v1/responses (#12969) 2026-04-20 04:16:13 -07:00
test_api_server_normalize.py
test_api_server_runs.py feat(api_server): add POST /v1/runs/{run_id}/stop endpoint 2026-04-25 18:40:35 -07:00
test_api_server_toolset.py
test_api_server.py fix(api-server): persist incomplete snapshot on asyncio.CancelledError too 2026-04-24 15:22:19 -07:00
test_approve_deny_commands.py
test_auth_fallback.py fix(gateway,cron): activate fallback_model when primary provider auth fails 2026-04-24 05:35:43 -07:00
test_auto_continue.py
test_background_command.py fix(gateway): close temporary agents after one-off tasks 2026-04-16 06:31:23 -07:00
test_background_process_notifications.py fix(gateway): don't treat group session user_id as thread_id in shutdown notifications (#10546) 2026-04-15 15:09:23 -07:00
test_base_topic_sessions.py
test_bluebubbles.py fix(gateway/bluebubbles): align iMessage delivery with non-editable UX 2026-04-24 16:04:37 -07:00
test_busy_session_ack.py feat(busy): add 'steer' as a third display.busy_input_mode option (#16279) 2026-04-26 18:21:29 -07:00
test_cancel_background_drain.py fix(gateway): cancel_background_tasks must drain late-arrivals (#12471) 2026-04-19 01:48:42 -07:00
test_channel_directory.py fix(Slack): resolve Slack channels by raw ID and enumerate joined channels 2026-04-26 12:29:02 -07:00
test_clean_shutdown_marker.py
test_command_bypass_active_session.py refactor(commands): drop /provider, /plan handler, and clean up slash registry (#15047) 2026-04-24 03:10:52 -07:00
test_complete_path_at_filter.py fix(tui): restore voice/panic handlers + scope fuzzy paths to cwd 2026-04-23 19:38:33 -05:00
test_compress_command.py fix(compress): don't reach into ContextCompressor privates from /compress (#15039) 2026-04-24 02:55:43 -07:00
test_compress_focus.py fix(compress): don't reach into ContextCompressor privates from /compress (#15039) 2026-04-24 02:55:43 -07:00
test_compress_plugin_engine.py fix(compress): don't reach into ContextCompressor privates from /compress (#15039) 2026-04-24 02:55:43 -07:00
test_config_cwd_bridge.py fix: enforce config.yaml as sole CWD source + deprecate .env CWD vars + add hermes memory reset (#11029) 2026-04-16 06:48:33 -07:00
test_config.py fix(gateway/config): coerce quoted boolean values in config parsing 2026-04-24 15:20:05 -07:00
test_debug_command.py fix(debug): sweep expired pending pastes on slash debug paths 2026-04-22 11:59:39 -07:00
test_delivery.py
test_dingtalk.py feat(dingtalk): AI Cards streaming, emoji reactions, and media handling 2026-04-17 19:26:53 -07:00
test_discord_allowed_channels.py fix(discord): honor wildcard '*' in ignored_channels and free_response_channels 2026-04-24 03:04:42 -07:00
test_discord_allowed_mentions.py fix(discord): default allowed_mentions to block @everyone and role pings 2026-04-17 04:08:42 -07:00
test_discord_attachment_download.py fix(discord): route attachment downloads through authenticated bot session (#11568) 2026-04-17 04:59:03 -07:00
test_discord_bot_auth_bypass.py fix(discord): harden DISCORD_ALLOWED_ROLES and cover gateway layer 2026-04-17 05:48:26 -07:00
test_discord_bot_filter.py
test_discord_channel_controls.py
test_discord_channel_prompts.py refactor: remove smart_model_routing feature (#12732) 2026-04-19 18:12:55 -07:00
test_discord_channel_skills.py
test_discord_connect.py fix(gateway/discord): read permission attrs from AppCommand, canonicalize contexts 2026-04-23 15:11:56 -07:00
test_discord_document_handling.py
test_discord_free_response.py fix(discord): skip auto-threading reply messages 2026-04-17 06:46:52 -07:00
test_discord_imports.py
test_discord_media_metadata.py
test_discord_model_picker.py test(gateway): unify discord mock via shared conftest; drop duplicated mock in model_picker test 2026-04-24 03:33:29 -07:00
test_discord_opus.py
test_discord_race_polish.py refactor(discord): slim down the race-polish fix (#12644) 2026-04-19 11:08:10 -07:00
test_discord_reactions.py
test_discord_reply_mode.py test(discord): update reply_mode fixture for new to_reference() wrapping 2026-04-17 04:17:56 -07:00
test_discord_send.py fix(discord): forum channel media + polish 2026-04-17 20:25:48 -07:00
test_discord_slash_commands.py refactor(commands): drop /provider, /plan handler, and clean up slash registry (#15047) 2026-04-24 03:10:52 -07:00
test_discord_system_messages.py
test_discord_thread_persistence.py
test_display_config.py fix(gateway): default Slack tool_progress to off 2026-04-26 18:33:35 -07:00
test_dm_topics.py fix(gateway): make Telegram DM topic config writes atomic 2026-04-20 00:57:53 -07:00
test_document_cache.py
test_duplicate_reply_suppression.py test: add cancellation handler delivery confirmation tests 2026-04-16 05:53:18 -07:00
test_email.py fix(email): add required Date header to outbound mail 2026-04-27 06:41:11 -07:00
test_extract_local_files.py
test_fallback_eviction.py
test_fast_command.py refactor: remove smart_model_routing feature (#12732) 2026-04-19 18:12:55 -07:00
test_feishu_approval_buttons.py
test_feishu_comment_rules.py feat: add Feishu document comment intelligent reply with 3-tier access control 2026-04-17 19:04:11 -07:00
test_feishu_comment.py feat: add Feishu document comment intelligent reply with 3-tier access control 2026-04-17 19:04:11 -07:00
test_feishu_onboard.py
test_feishu.py fix(feishu): correct identity model docs and prefer tenant-scoped user_id 2026-04-22 18:06:22 -07:00
test_gateway_inactivity_timeout.py
test_gateway_shutdown.py fix(gateway,cron): close ephemeral agents + reap stale aux clients (salvage #13979) (#16598) 2026-04-27 07:41:42 -07:00
test_homeassistant.py test: remove 169 change-detector tests across 21 files (#11472) 2026-04-17 01:05:09 -07:00
test_hooks.py feat(gateway): expose plugin slash commands natively on all platforms + decision-capable command hook 2026-04-22 16:23:21 -07:00
test_insights_unicode_flags.py fix(model-switch): normalize Unicode dashes from Telegram/iOS input 2026-04-15 17:54:16 -07:00
test_internal_event_bypass_pairing.py test(conftest): reset module-level state + unset platform allowlists (#13400) 2026-04-21 01:33:10 -07:00
test_interrupt_key_match.py
test_matrix_mention.py fix(matrix): E2EE and migration bugfixes (#10860) 2026-04-17 04:03:02 +05:30
test_matrix_voice.py fix(ci): resolve 4 pre-existing main failures (docs lint + 3 stale tests) (#11373) 2026-04-16 20:43:41 -07:00
test_matrix.py fix(matrix): close 'hall of mirrors' pairing + echo loop (#15763) (#16374) 2026-04-26 21:50:28 -07:00
test_mattermost.py test: remove 169 change-detector tests across 21 files (#11472) 2026-04-17 01:05:09 -07:00
test_media_download_retry.py fix(slack): harden attachment handling 2026-04-26 18:20:17 -07:00
test_media_extraction.py
test_message_deduplicator.py Fix MessageDeduplicator max_size enforcement 2026-04-26 18:51:51 -07:00
test_mirror.py fix(gateway): avoid cross-user mirror writes in per-user group sessions 2026-04-26 18:31:24 -07:00
test_model_command_custom_providers.py
test_model_switch_persistence.py
test_pairing.py
test_pending_drain_race.py fix(gateway): close pending-drain and late-arrival races in base adapter (#12371) 2026-04-18 19:32:26 -07:00
test_pending_event_none.py fix(gateway): stop typing loops on session interrupt 2026-04-19 03:03:57 -07:00
test_pii_redaction.py
test_platform_base.py
test_platform_reconnect.py
test_pre_gateway_dispatch.py feat(plugins): add pre_gateway_dispatch hook 2026-04-24 03:02:03 -07:00
test_proxy_mode.py fix(telegram): honor no_proxy for explicit proxy setup 2026-04-24 14:31:04 -07:00
test_qqbot.py fix(qqbot): add back-compat for env var rename; drop qrcode core dep 2026-04-17 15:31:14 -07:00
test_queue_consumption.py fix(gateway): /queue is now a true FIFO — each invocation gets its own turn (#16175) 2026-04-26 11:55:09 -07:00
test_reasoning_command.py fix(gateway): make reasoning session-scoped by default 2026-04-25 18:01:31 -07:00
test_reply_to_injection.py fix(gateway): always inject reply-to pointer, not just when quoted text is absent (#13676) 2026-04-21 13:33:02 -07:00
test_restart_drain.py feat(busy): add 'steer' as a third display.busy_input_mode option (#16279) 2026-04-26 18:21:29 -07:00
test_restart_notification.py
test_restart_redelivery_dedup.py fix(gateway): ignore redelivered /restart after PTB offset ACK fails (#11940) 2026-04-17 21:17:33 -07:00
test_restart_resume_pending.py fix(gateway): mark only still-running sessions resume_pending on drain timeout (#12332) 2026-04-18 17:40:34 -07:00
test_resume_command.py refactor(memory): remove flush_memories entirely (#15696) 2026-04-25 08:21:14 -07:00
test_retry_replacement.py
test_retry_response.py
test_run_progress_interrupt.py fix(gateway): suppress tool-progress bubbles after interrupt (#16034) 2026-04-26 05:47:37 -07:00
test_run_progress_topics.py fix(gateway/bluebubbles): align iMessage delivery with non-editable UX 2026-04-24 16:04:37 -07:00
test_runner_fatal_adapter.py
test_runner_startup_failures.py fix(gateway): only clear locks belonging to the replaced process 2026-04-23 15:07:06 -07:00
test_running_agent_session_toggles.py refactor: drop persist_session plumbing + fix broken btw mid-turn bypass (#16075) 2026-04-26 07:15:23 -07:00
test_safe_adapter_disconnect.py fix(gateway): close adapter resources when connect() fails or raises (#12339) 2026-04-18 18:53:31 -07:00
test_send_image_file.py
test_send_retry.py
test_session_boundary_hooks.py refactor(memory): remove flush_memories entirely (#15696) 2026-04-25 08:21:14 -07:00
test_session_boundary_security_state.py fix(gateway): bypass slash commands during pending update prompts 2026-04-26 18:39:44 -07:00
test_session_dm_thread_seeding.py
test_session_env.py fix(tests): resolve remaining CI failures — commit_memory_session, already_sent, timezone leak, session env (#10785) 2026-04-16 02:26:14 -07:00
test_session_hygiene.py fix(gateway): close temporary agents after one-off tasks 2026-04-16 06:31:23 -07:00
test_session_info.py fix(context): honor custom_providers context_length on /model switch + bump probe tier to 256K (#15844) 2026-04-25 18:47:53 -07:00
test_session_list_allowed_sources.py fix(sessions): /save lands under $HERMES_HOME, widen browse+TUI picker, force-refresh ollama-cloud on setup (#16296) 2026-04-26 18:49:48 -07:00
test_session_model_override_routing.py fix(gateway): make reasoning session-scoped by default 2026-04-25 18:01:31 -07:00
test_session_model_reset.py fix(gateway): clear stale pending model note on session reset 2026-04-26 19:01:50 -07:00
test_session_race_guard.py fix(gateway): stop typing loops on session interrupt 2026-04-19 03:03:57 -07:00
test_session_reset_notify.py
test_session_split_brain_11016.py fix(gateway): guard-match the finally-block _active_sessions delete 2026-04-23 05:15:52 -07:00
test_session_state_cleanup.py fix(gateway): consolidate per-session cleanup; close SessionDB on shutdown (#11800) 2026-04-17 15:18:23 -07:00
test_session_store_prune.py fix(gateway): pass session_key (not session_id) to active-process check during prune 2026-04-20 03:10:19 -07:00
test_session.py fix(slack): extract rich_text quotes/lists and link unfurl previews 2026-04-26 13:02:51 -07:00
test_setup_feishu.py
test_shared_group_sender_prefix.py fix(gateway): preserve sender attribution in shared group sessions 2026-04-21 00:54:46 -07:00
test_shutdown_cache_cleanup.py fix(gateway): clean up cached agents on shutdown (#11205) 2026-04-26 12:51:53 -07:00
test_shutdown_memory_provider_messages.py fix(gateway): pass session messages to shutdown_memory_provider (#15165) 2026-04-27 06:41:16 -07:00
test_signal.py test(conftest): reset module-level state + unset platform allowlists (#13400) 2026-04-21 01:33:10 -07:00
test_slack_approval_buttons.py fix(slack): preserve thread-parent context when cron/bot posted the parent 2026-04-26 12:35:16 -07:00
test_slack_channel_skills.py feat(gateway/slack): support channel_skill_bindings 2026-04-26 18:25:41 -07:00
test_slack_mention.py fix(slack): skip _mentioned_threads registration when strict_mention is on 2026-04-26 12:23:20 -07:00
test_slack.py fix(slack): honor NO_PROXY for Slack transport 2026-04-26 18:33:35 -07:00
test_sms.py test: remove 169 change-detector tests across 21 files (#11472) 2026-04-17 01:05:09 -07:00
test_sse_agent_cancel.py
test_ssl_certs.py
test_status_command.py test(gateway): cover Slack vs non-Slack home-channel onboarding hint 2026-04-26 11:56:23 -07:00
test_status.py fix(gateway,cron): close ephemeral agents + reap stale aux clients (salvage #13979) (#16598) 2026-04-27 07:41:42 -07:00
test_steer_command.py feat(steer): /steer <prompt> injects a mid-run note after the next tool call (#12116) 2026-04-18 04:17:18 -07:00
test_step_callback_compat.py
test_sticker_cache.py
test_stream_consumer_fresh_final.py feat(telegram): send fresh finals for stale preview streams (port openclaw#72038) (#16261) 2026-04-26 17:26:37 -07:00
test_stream_consumer.py fix(gateway): accept finalize kwarg in all platform edit_message overrides 2026-04-19 22:46:47 -07:00
test_stt_config.py
test_stuck_loop.py fix: break stuck session resume loops after repeated restarts (#7536) 2026-04-14 17:08:35 -07:00
test_telegram_approval_buttons.py feat(telegram): add config option to disable link previews 2026-04-15 17:54:43 -07:00
test_telegram_caption_merge.py
test_telegram_conflict.py
test_telegram_documents.py fix(telegram): cache inbound videos and accept mp4 uploads 2026-04-20 05:10:23 -07:00
test_telegram_format.py feat(telegram): auto-wrap markdown tables in code blocks (#11794) 2026-04-17 14:27:26 -07:00
test_telegram_group_gating.py fix(telegram): accept /cmd@botname from bot menu in groups 2026-04-26 22:00:18 -07:00
test_telegram_mention_boundaries.py refactor(telegram): use entity-only mention detection 2026-04-20 00:10:22 -07:00
test_telegram_network_reconnect.py
test_telegram_network.py fix(telegram): honor no_proxy for explicit proxy setup 2026-04-24 14:31:04 -07:00
test_telegram_photo_interrupts.py
test_telegram_reactions.py
test_telegram_reply_mode.py
test_telegram_text_batching.py
test_telegram_thread_fallback.py fix(telegram): restore typing indicator and thread routing for forum General topic 2026-04-15 22:35:19 -07:00
test_telegram_webhook_secret.py fix(telegram): require TELEGRAM_WEBHOOK_SECRET in webhook mode (#13527) 2026-04-21 06:23:09 -07:00
test_text_batching.py fix(discord): shield text-batch flush from follow-up cancel (#12444) 2026-04-19 00:09:38 -07:00
test_title_command.py
test_transcript_offset.py
test_unauthorized_dm_behavior.py refactor(gateway): extract WhatsApp identity helpers into shared module 2026-04-24 07:55:55 -07:00
test_unknown_command.py feat(gateway): expose plugin slash commands natively on all platforms + decision-capable command hook 2026-04-22 16:23:21 -07:00
test_update_command.py
test_update_streaming.py fix(gateway): unblock update subprocess on recognized-command bypass 2026-04-26 18:39:44 -07:00
test_usage_command.py feat(/usage): append account limits section in CLI and gateway 2026-04-21 01:56:35 -07:00
test_verbose_command.py fix(gateway): default Slack tool_progress to off 2026-04-26 18:33:35 -07:00
test_voice_command.py fix(gateway): honor voice.auto_tts config in auto-TTS gate (#16007) (#16039) 2026-04-26 05:52:05 -07:00
test_voice_mode_platform_isolation.py test(voice): update existing voice_mode tests for platform-prefixed keys 2026-04-19 22:36:00 -07:00
test_weak_credential_guard.py
test_webhook_adapter.py
test_webhook_deliver_only.py feat(webhook): direct delivery mode for zero-LLM push notifications (#12473) 2026-04-19 05:18:19 -07:00
test_webhook_dynamic_routes.py
test_webhook_integration.py
test_webhook_signature_rate_limit.py fix(webhook): validate HMAC signature before rate limiting (#12544) 2026-04-19 22:45:08 -07:00
test_wecom_callback.py
test_wecom.py fix(wecom): bound req_id cache, revert undocumented is_group change, add tests 2026-04-17 19:03:29 -07:00
test_weixin.py Fix Weixin media uploads and refresh lockfile 2026-04-17 06:50:36 -07:00
test_whatsapp_connect.py fix(whatsapp): kill bridge process tree on Windows disconnect 2026-04-20 20:49:32 -07:00
test_whatsapp_formatting.py
test_whatsapp_group_gating.py feat(whatsapp): add dm_policy and group_policy parity with WeCom/Weixin/QQ adapters 2026-04-20 11:56:19 -07:00
test_whatsapp_reply_prefix.py
test_ws_auth_retry.py
test_yolo_command.py