From ea42e6a6c7d15c5588396368f03797ce11e29e89 Mon Sep 17 00:00:00 2001 From: yuandonghao Date: Wed, 24 Jun 2026 18:09:56 +0800 Subject: [PATCH] fix(tools): break admin_tools circular import in split facade After rebasing onto dev (#3629 moved the admin manage_* tools into src/agent_tools/admin_tools), the facade re-exported them via a top-level `from src.agent_tools.admin_tools import ...`. But src.agent_tools.__init__ imports this facade at top level, so the eager import re-entered the partially-initialized agent_tools package and broke collection. Re-export the admin symbols (do_manage_endpoints/mcp/webhooks/tokens/ settings, _MCP_DENIED_COMMANDS, _validate_mcp_command) lazily through module __getattr__ instead, and drop them from src/tools/__init__ (they no longer live in the src.tools package). system.py now holds only the skills/tasks/api bridges; admin tools live solely in admin_tools.py, matching upstream. Co-Authored-By: Claude Opus 4.8 --- src/tool_implementations.py | 20 ++++++++++++++++---- src/tools/__init__.py | 3 +-- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/tool_implementations.py b/src/tool_implementations.py index e38f30ede..e1c7c24b2 100644 --- a/src/tool_implementations.py +++ b/src/tool_implementations.py @@ -19,11 +19,23 @@ from src.tools.system import ( # noqa: F401 do_api_call, do_app_api, _APP_API_BLOCKLIST_PREFIXES, _APP_API_BLOCKLIST_METHOD_PATH, ) -from src.agent_tools.admin_tools import ( # noqa: F401 - do_manage_endpoints, do_manage_mcp, do_manage_webhooks, - do_manage_tokens, do_manage_settings, - _MCP_DENIED_COMMANDS, _validate_mcp_command, +# Admin manage_* tools (endpoints/mcp/webhooks/tokens/settings) live in +# src/agent_tools/admin_tools after the upstream registry migration (#3629). +# Re-exported lazily via __getattr__: src.agent_tools.__init__ imports this +# facade at top level, so a eager `from src.agent_tools.admin_tools import` +# here would re-enter the partially-initialized agent_tools package (circular). +_ADMIN_TOOL_SYMBOLS = ( + "do_manage_endpoints", "do_manage_mcp", "do_manage_webhooks", + "do_manage_tokens", "do_manage_settings", + "_MCP_DENIED_COMMANDS", "_validate_mcp_command", ) + + +def __getattr__(name): + if name in _ADMIN_TOOL_SYMBOLS: + from src.agent_tools import admin_tools + return getattr(admin_tools, name) + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") # Cookbook (model serving) domain extracted to src/tools/cookbook.py # (slice 1, #4082/#4071). Re-imported here so this module stays a working # facade. cookbook.py pulls `_internal_headers` / `_INTERNAL_BASE` back diff --git a/src/tools/__init__.py b/src/tools/__init__.py index 7f847488e..5e18f4f92 100644 --- a/src/tools/__init__.py +++ b/src/tools/__init__.py @@ -5,8 +5,7 @@ re-exports from here for backward compatibility. """ from src.tools._common import _parse_tool_args # noqa: F401 from src.tools.system import ( # noqa: F401 - do_manage_skills, _skill_dump, do_manage_tasks, do_manage_endpoints, - do_manage_mcp, do_manage_webhooks, do_manage_tokens, do_manage_settings, + do_manage_skills, _skill_dump, do_manage_tasks, do_api_call, do_app_api, ) from src.tools.cookbook import ( # noqa: F401