From a5bd246865bda88feb84d3289e76deabaece0ece Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Mon, 28 Sep 2026 10:21:41 -0700 Subject: [PATCH] Old pre-decomposition import paths are gone: plugin compat layer removed on schedule (#126164) * refactor(plugins): remove the Sep 2026 decomposition compat layer on schedule The PLUGIN-COMPAT layer (2776813df3b + d63e3803240 + 0a5164cebe5) kept pre-#102117 import paths alive for external plugins until 2026-09-14. That window closed two weeks ago; since then the loader has already been skipping plugins that use the old paths. This removes the layer itself: - 328 appended `PLUGIN-COMPAT` blocks (lazy `__getattr__` pointer tables, re-exported third-party names, restored dead definitions) and the three re-export stub modules (gateway/startup_watchdog, hermes_cli/observability/relay_runtime, tools/environments/modal_utils) - COMPAT_MANIFEST.md, compat_manifest.json, scripts/check_compat_pointers.py and its lint step - the reporting surfaces: CLI banner notice, `hermes plugins compat`, the `hermes doctor` section, the post-update notice, the Desktop one-time dialog, the loader's pre-import skip and the `plugins.allow_deprecated_imports` escape hatch An external plugin that still imports an old path now fails to load with its ImportError as the reason in `hermes plugins list`, the same path as any broken plugin. hermes_cli/plugin_compat.py stays as three inert stubs (compat_report, removal_in_effect, summary_lines): an already-running pre-removal `hermes update` lazy-imports them after the checkout swap (tests/compat/old_updater_surface.json). In-tree fallout, both already dead: hermes_cli/setup.py::_check_espeak_ng (no callers; its `shutil` came from a compat block) and gateway/config.py::SessionResetPolicy ("retained solely for the scheduled plugin-compat window"). Two test_run_agent patches targeted the removed `run_agent.handle_function_call` pointer; they now patch `model_tools.handle_function_call`, the seam production reads, like every sibling test in that file. * chore: retrigger CI (zero-job startup_failure phantom) * test: drop resolution allowlist rows for the two deleted which() sites hermes_cli/setup.py::_check_espeak_ng (dead) and tools/skillevaluator_scan.py::scanner_available (a restored definition inside a PLUGIN-COMPAT block) no longer exist; the stale-row gate requires their allowlist entries go with them. --- .github/workflows/lint.yml | 6 - AGENTS.md | 12 +- COMPAT_MANIFEST.md | 3857 ----- acp_adapter/auth.py | 11 - acp_adapter/edit_approval.py | 16 - acp_adapter/events.py | 8 - acp_adapter/server.py | 37 - acp_adapter/session.py | 8 - agent/agent_init.py | 22 - agent/agent_runtime_helpers.py | 27 - agent/anthropic_adapter.py | 44 - agent/aux_accounting.py | 11 - agent/auxiliary_client.py | 29 - agent/backend_identity.py | 21 - agent/background_review.py | 36 - agent/bedrock_adapter.py | 111 - agent/bounded_response.py | 23 - agent/browser_provider.py | 9 - agent/browser_registry.py | 25 - agent/codex_runtime.py | 18 - agent/coding_context.py | 32 - agent/context_compressor.py | 22 - agent/conversation_compression.py | 10 - agent/conversation_loop.py | 62 - agent/credential_sources.py | 11 - agent/display.py | 11 - agent/error_surface.py | 9 - agent/estop.py | 8 - agent/file_safety.py | 83 - agent/image_gen_provider.py | 10 - agent/image_gen_registry.py | 25 - agent/learning_graph_render.py | 11 - agent/lsp/eventlog.py | 26 - agent/lsp/protocol.py | 9 - agent/monitoring/cron_health.py | 23 - agent/monitoring/emitter.py | 9 - agent/monitoring/gateway_health.py | 21 - agent/monitoring/gateway_health_export.py | 8 - agent/nous_rate_guard.py | 23 - agent/outbound_webhooks.py | 10 - agent/pet/generate/atlas.py | 21 - agent/prompt_builder.py | 23 - agent/prompt_cache_boundary.py | 12 - agent/proxy_sources/iron_proxy.py | 8 - agent/reasoning_effort.py | 9 - agent/relay_llm.py | 8 - agent/relay_runtime.py | 88 - agent/relay_tools.py | 9 - agent/review_idle_queue.py | 8 - agent/secret_sources/_cache.py | 23 - agent/secret_sources/bitwarden.py | 111 - agent/secret_sources/command.py | 191 - agent/secret_sources/onepassword.py | 23 - agent/shell_hooks.py | 8 - agent/skill_bundles.py | 8 - agent/skill_utils.py | 17 - agent/system_prompt.py | 22 - agent/terminal_env_registry.py | 24 - agent/transcript_repair.py | 8 - agent/transcription_provider.py | 24 - agent/transcription_registry.py | 26 - agent/transports/chat_completions.py | 8 - agent/transports/codex.py | 10 - agent/transports/codex_app_server.py | 9 - agent/tts_registry.py | 26 - agent/turn_context.py | 26 - agent/turn_retry_state.py | 8 - agent/usage_pricing.py | 9 - agent/video_gen_provider.py | 10 - agent/video_gen_registry.py | 25 - agent/web_search_provider.py | 8 - agent/web_search_registry.py | 25 - apps/desktop/electron/main.ts | 67 - .../electron/plugin-compat-notice.test.ts | 81 - apps/desktop/electron/plugin-compat-notice.ts | 143 - cli.py | 80 - compat_manifest.json | 12510 ---------------- cron/jobs.py | 11 - cron/scheduler.py | 28 - cron/scheduler_provider.py | 23 - gateway/browser_control_artifacts.py | 10 - gateway/browser_control_broker.py | 13 - gateway/config.py | 40 - gateway/delivery_ledger.py | 30 - gateway/disk_status.py | 23 - gateway/hosted_room_discussion.py | 8 - gateway/hosted_room_driver.py | 11 - gateway/hosted_room_execution_policy.py | 9 - gateway/hosted_room_peer.py | 54 - gateway/hosted_room_replicas.py | 25 - gateway/hosted_rooms.py | 11 - gateway/kanban_watchers.py | 27 - gateway/memory_status.py | 23 - gateway/platforms/helpers.py | 95 - gateway/platforms/qqbot/adapter.py | 10 - gateway/platforms/qqbot/chunked_upload.py | 11 - gateway/platforms/qqbot/keyboards.py | 96 - gateway/platforms/signal.py | 24 - gateway/platforms/weixin.py | 10 - gateway/platforms/yuanbao.py | 202 - gateway/platforms/yuanbao_media.py | 9 - gateway/platforms/yuanbao_proto.py | 78 - gateway/relay/__init__.py | 19 - gateway/relay/adapter.py | 8 - gateway/relay/auth.py | 99 - gateway/response_filters.py | 9 - gateway/restart_loop_guard.py | 34 - gateway/run.py | 72 - gateway/session.py | 29 - gateway/slash_access.py | 8 - gateway/slash_commands.py | 33 - gateway/startup_watchdog.py | 6 - gateway/status.py | 22 - gateway/sticker_cache.py | 9 - gateway/stream_consumer.py | 23 - gateway/stream_dispatch.py | 22 - gateway/systemd_notify.py | 8 - hermes_cli/agent_import.py | 25 - hermes_cli/auth.py | 48 - hermes_cli/backup.py | 30 - hermes_cli/browser_connect.py | 10 - hermes_cli/callbacks.py | 123 - hermes_cli/checkpoints.py | 23 - hermes_cli/cli_info_mixin.py | 16 - hermes_cli/commands.py | 257 - hermes_cli/config.py | 55 - hermes_cli/config_defaults.py | 4 - hermes_cli/console_engine.py | 8 - hermes_cli/curses_ui.py | 8 - hermes_cli/dashboard_auth/audit.py | 8 - hermes_cli/dashboard_auth/middleware.py | 22 - hermes_cli/dingtalk_auth.py | 23 - hermes_cli/doctor.py | 55 +- hermes_cli/doctor_config.py | 17 - hermes_cli/doctor_live.py | 17 - hermes_cli/focus_view.py | 22 - hermes_cli/foreign_sessions.py | 63 - hermes_cli/gateway.py | 35 - hermes_cli/gitlock.py | 30 - hermes_cli/heartbeat.py | 8 - hermes_cli/journey.py | 10 - hermes_cli/kanban.py | 8 - hermes_cli/kanban_db.py | 85 - hermes_cli/kanban_decompose.py | 9 - hermes_cli/kanban_diagnostics.py | 19 - hermes_cli/local_runtime/binaries.py | 22 - hermes_cli/local_runtime/bootstrap.py | 22 - hermes_cli/local_runtime/capabilities.py | 9 - hermes_cli/local_runtime/catalog.py | 19 - hermes_cli/local_runtime/hf_browse.py | 8 - hermes_cli/main.py | 28 - hermes_cli/mcp_picker.py | 22 - hermes_cli/mcp_security.py | 10 - hermes_cli/middleware.py | 26 - hermes_cli/moa_config.py | 34 - hermes_cli/model_setup_flows.py | 28 - hermes_cli/model_switch.py | 28 - hermes_cli/models.py | 83 - hermes_cli/nous_billing.py | 9 - hermes_cli/nous_subscription.py | 22 - hermes_cli/observability/relay_runtime.py | 6 - .../observability/relay_shared_metrics.py | 43 - hermes_cli/onepassword_secrets_cli.py | 24 - hermes_cli/platform_actions.py | 8 - hermes_cli/plugin_compat.py | 369 +- hermes_cli/plugins.py | 80 - hermes_cli/plugins_cmd.py | 11 +- hermes_cli/plugins_cmd_listing.py | 36 - hermes_cli/plugins_loader.py | 9 - hermes_cli/profile_describer.py | 8 - hermes_cli/profile_distribution.py | 22 - hermes_cli/profiles.py | 14 - hermes_cli/runtime_provider.py | 24 - hermes_cli/security_advisories.py | 24 - hermes_cli/setup.py | 38 - hermes_cli/slack_cli.py | 8 - hermes_cli/sqlite_safe_read.py | 9 - hermes_cli/status.py | 27 - hermes_cli/subcommands/plugins.py | 11 - hermes_cli/telegram_managed_bot.py | 95 - hermes_cli/tools_config.py | 31 - hermes_cli/update_cmd.py | 11 - hermes_cli/update_cmd_maint.py | 11 - hermes_cli/update_inventory.py | 9 - hermes_cli/web_deps.py | 23 - hermes_cli/web_routers/cron.py | 8 - hermes_cli/web_routers/mcp.py | 8 - hermes_cli/web_routers/sessions.py | 10 - hermes_cli/web_routers/skills.py | 23 - hermes_cli/web_routers/tools.py | 23 - hermes_cli/web_server.py | 407 - hermes_cli/webhook.py | 24 - hermes_cli/win_pty_bridge.py | 8 - hermes_logging.py | 15 - hermes_state.py | 76 - hermes_state_registry.py | 16 - hermes_state_search.py | 9 - plugins/AGENTS.md | 18 +- plugins/browser/browser_use/provider.py | 23 - plugins/browser/browserbase/provider.py | 24 - plugins/browser/firecrawl/provider.py | 24 - plugins/context_engine/__init__.py | 9 - plugins/cron_providers/__init__.py | 9 - plugins/cron_providers/chronos/__init__.py | 8 - plugins/cron_providers/chronos/_nas_client.py | 8 - plugins/dashboard_auth/basic/__init__.py | 23 - plugins/dashboard_auth/drain/__init__.py | 22 - plugins/dashboard_auth/nous/__init__.py | 31 - .../dashboard_auth/self_hosted/__init__.py | 28 - plugins/google_meet/audio_bridge.py | 30 - plugins/google_meet/meet_bot.py | 12 - plugins/google_meet/node/cli.py | 8 - plugins/google_meet/node/registry.py | 8 - plugins/image_gen/deepinfra/__init__.py | 25 - plugins/image_gen/fal/__init__.py | 23 - plugins/image_gen/krea/__init__.py | 25 - plugins/image_gen/openai/__init__.py | 26 - plugins/image_gen/xai/__init__.py | 26 - plugins/memory/honcho/__init__.py | 215 - plugins/memory/honcho/client.py | 22 - plugins/memory/honcho/oauth.py | 8 - plugins/memory/honcho/session.py | 11 - plugins/memory/mem0/__init__.py | 79 - plugins/memory/mem0/_setup.py | 16 - plugins/memory/retaindb/__init__.py | 134 - plugins/memory/supermemory/__init__.py | 56 - plugins/platforms/a2a/protocol.py | 47 - plugins/platforms/a2a/security.py | 83 - plugins/platforms/a2a/tools.py | 8 - plugins/platforms/dingtalk/adapter.py | 41 - plugins/platforms/discord/adapter.py | 22 - plugins/platforms/feishu/feishu_comment.py | 95 - plugins/platforms/google_chat/oauth.py | 24 - plugins/platforms/irc/adapter.py | 8 - plugins/platforms/line/adapter.py | 8 - plugins/platforms/matrix/adapter.py | 29 - plugins/platforms/ntfy/adapter.py | 8 - plugins/platforms/photon/adapter.py | 23 - plugins/platforms/photon/auth.py | 48 - plugins/platforms/photon/cli.py | 23 - plugins/platforms/raft/adapter.py | 8 - plugins/platforms/teams/adapter.py | 24 - plugins/platforms/telegram/adapter.py | 24 - plugins/platforms/telegram/telegram_ids.py | 11 - plugins/platforms/wecom/adapter.py | 49 - plugins/spotify/__init__.py | 28 - plugins/spotify/client.py | 12 - plugins/spotify/tools.py | 23 - plugins/teams_pipeline/cli.py | 26 - plugins/teams_pipeline/meetings.py | 45 - plugins/teams_pipeline/pipeline.py | 8 - plugins/teams_pipeline/subscriptions.py | 29 - plugins/video_gen/fal/__init__.py | 8 - plugins/video_gen/xai/__init__.py | 60 - plugins/web/brave_free/provider.py | 23 - plugins/web/ddgs/provider.py | 22 - plugins/web/exa/provider.py | 23 - plugins/web/firecrawl/provider.py | 25 - plugins/web/keenable/provider.py | 22 - plugins/web/parallel/provider.py | 22 - plugins/web/searxng/provider.py | 23 - plugins/web/tavily/provider.py | 22 - plugins/web/xai/provider.py | 22 - providers/__init__.py | 22 - run_agent.py | 51 - scripts/check_compat_pointers.py | 111 - tests/agent/test_run_agent.py | 4 +- tests/evals/test_codebase_navigability.py | 2 +- tests/fixtures/resolution_allowlist.json | 10 - .../test_compat_manifest_targets.py | 103 - tests/hermes_cli/test_plugin_compat_notice.py | 145 - .../test_plugin_compat_scan_cache.py | 43 - tests/scripts/test_check_compat_pointers.py | 51 - tests/scripts/test_compat_inventory.py | 23 - tests/tools/test_plugin_compat_warning.py | 69 - tools/apply_layout_tool.py | 8 - tools/approval.py | 50 - tools/async_delegation.py | 20 - tools/browser_camofox_state.py | 11 - tools/browser_dialog_tool.py | 23 - tools/browser_supervisor.py | 39 - tools/browser_tool.py | 50 - tools/clarify_gateway.py | 24 - tools/close_preview_tool.py | 49 - tools/code_execution_tool.py | 27 - tools/code_kernel_remote.py | 8 - tools/computer_use/__init__.py | 27 - tools/computer_use/cua_backend.py | 36 - tools/computer_use/permissions.py | 8 - tools/computer_use/tool.py | 8 - tools/cronjob_tools.py | 23 - tools/delegate_tool.py | 38 - tools/delegation_live_log.py | 11 - tools/delegation_output_schema.py | 9 - tools/discord_tool.py | 13 - tools/drive_preview_tool.py | 8 - tools/env_probe.py | 8 - tools/environments/base.py | 30 - tools/environments/managed_modal.py | 8 - tools/environments/modal_utils.py | 6 - tools/environments/vercel_sandbox.py | 8 - tools/feishu_doc_tool.py | 25 - tools/feishu_drive_tool.py | 9 - tools/file_operations.py | 50 - tools/file_tools.py | 28 - tools/focus_pane_tool.py | 28 - tools/fuzzy_match.py | 9 - tools/image_generation_tool.py | 11 - tools/managed_tool_gateway.py | 205 - tools/mcp_oauth.py | 18 - tools/mcp_schema_cache.py | 17 - tools/mcp_tool.py | 58 - tools/memory_tool.py | 24 - tools/microsoft_graph_client.py | 23 - tools/open_preview_tool.py | 53 - tools/openrouter_client.py | 23 - tools/path_security.py | 23 - tools/preview_tool.py | 11 - tools/process_registry.py | 9 - tools/react_to_message_tool.py | 22 - tools/read_extract.py | 9 - tools/read_preview_tool.py | 55 - tools/read_terminal_tool.py | 8 - tools/read_window_tool.py | 23 - tools/send_message_tool.py | 63 - tools/skill_ledger.py | 13 - tools/skill_linter.py | 14 - tools/skill_manager_tool.py | 22 - tools/skill_usage.py | 63 - tools/skillevaluator_scan.py | 13 - tools/skills_guard.py | 11 - tools/skills_hub.py | 86 - tools/skills_sync.py | 36 - tools/skills_sync_client.py | 70 - tools/skills_tool.py | 27 - tools/slash_confirm.py | 34 - tools/terminal_scope.py | 24 - tools/terminal_tool.py | 40 - tools/tool_result_storage.py | 10 - tools/tool_search.py | 45 - tools/transcription_tools.py | 48 - tools/tts_tool.py | 107 - tools/url_safety.py | 57 - tools/vision_tools.py | 10 - tools/voice_mode.py | 58 - tools/web_result_cache.py | 9 - tools/web_tools.py | 37 - tools/website_policy.py | 13 - tools/write_approval.py | 10 - tools/yuanbao_tools.py | 9 - toolsets.py | 25 - tui_gateway/AGENTS.md | 1 - tui_gateway/compute_host.py | 82 - tui_gateway/hosted_room_driver.py | 13 - tui_gateway/hosted_room_service.py | 8 - tui_gateway/mcp_rpc_helpers.py | 31 - tui_gateway/methods_browser_control.py | 24 - tui_gateway/methods_prompt.py | 8 - .../gateway-session-lifecycle.md | 3 +- website/docs/developer-guide/plugins/index.md | 19 +- 360 files changed, 36 insertions(+), 27747 deletions(-) delete mode 100644 COMPAT_MANIFEST.md delete mode 100644 apps/desktop/electron/plugin-compat-notice.test.ts delete mode 100644 apps/desktop/electron/plugin-compat-notice.ts delete mode 100644 compat_manifest.json delete mode 100644 gateway/startup_watchdog.py delete mode 100644 hermes_cli/observability/relay_runtime.py delete mode 100644 scripts/check_compat_pointers.py delete mode 100644 tests/hermes_cli/test_compat_manifest_targets.py delete mode 100644 tests/hermes_cli/test_plugin_compat_notice.py delete mode 100644 tests/hermes_cli/test_plugin_compat_scan_cache.py delete mode 100644 tests/scripts/test_check_compat_pointers.py delete mode 100644 tests/scripts/test_compat_inventory.py delete mode 100644 tests/tools/test_plugin_compat_warning.py delete mode 100644 tools/environments/modal_utils.py diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 6530567435..9ed41a2db6 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -168,12 +168,6 @@ jobs: - name: Require portable Bash shebangs run: python scripts/check_bash_shebangs.py - # The Sep 2026 decomposition kept old import paths alive for external plugins - # (PLUGIN-COMPAT blocks, see COMPAT_MANIFEST.md). They are removed on schedule by - # reverting one commit, so in-tree code must never depend on them. - - name: Forbid in-tree use of plugin-compat pointers - run: python scripts/check_compat_pointers.py - # /tmp is not portable (Termux has none, native Windows has none, macOS aliases it to # /private/tmp, Linux mounts it as a small tmpfs). Production code resolves scratch space # through the scratch-dir helper; skills, docs and prompts must not teach the model a diff --git a/AGENTS.md b/AGENTS.md index 832df27767..65aa3e61bc 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -217,7 +217,7 @@ hermes-agent/ ├── acp_adapter/ # ACP server (VS Code / Zed / JetBrains) ├── cron/ # jobs.py + scheduler.py (+ scheduler_*.py) ├── evals/ # Offline benchmarks (codebase_navigability/, compaction/, ...) -├── scripts/ # run_tests.sh, release.py, check_compat_pointers.py, ci/ +├── scripts/ # run_tests.sh, release.py, ci/ ├── website/ # Docusaurus docs (developer-guide/ holds the long-form area docs) └── tests/ # Pytest suite (~39k tests / ~3.7k files, Sep 2026) ``` @@ -246,18 +246,14 @@ families: `hermes_state.py` (21), `gateway/run.py` (15), `tools/mcp_tool.py` (15 function so `monkeypatch.setattr(facade, "name", ...)` is the seam; a patch on the defining module passes silently. Check the call site's binding before writing a patch target (blind repointing to defining modules broke 130+ tests). -- **Compat pointers are OFF LIMITS in-tree.** Old import paths kept alive for external plugins - (`PLUGIN-COMPAT` blocks, `COMPAT_MANIFEST.md`, `compat_manifest.json`) must not be used by - in-tree code or tests; `scripts/check_compat_pointers.py` runs in CI, and - `-W error::hermes_cli.plugin_compat.HermesPluginCompatWarning` catches them in the suite. - They are removed 2026-09-14 by reverting one commit. Import from the defining module. - **Don't recreate god files.** A file passing ~2,000 lines or a function passing ~300 lines / cyclomatic complexity 30 is the signal to split along `_` FIRST, in its own commit. New behaviour goes in a new or topical sibling — never appended to a facade. - **No `if/elif` ladders ≥ 4 branches keyed on a name/kind** — use a dict/table → handler (`_SLASH_DISPATCH` in `cli.py`, `_command_handler_table` in the gateway are the shape). - **No re-export shims for internal moves** ("keep the old name importable"). Internal paths - are not API; external compat is handled ONCE by the compat layer, not per PR. + are not API: plugins build on `ctx` and the documented ABCs. The one-time Sep 2026 + decomposition compat layer for external plugins has been removed; never reintroduce one. - **Moving a symbol means fixing its docs in the same PR:** grep `website/docs`, `skills/`, and every `AGENTS.md` for the old `path.py` + symbol (23 doc files went stale after the refactor). `evals/codebase_navigability/static_metrics.py