mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-24 10:52:21 +00:00
fix(tools): preserve core tools when a platform bundle is disabled
When a platform-bundle name (e.g. `hermes-yuanbao`, or any `hermes-*`) lands in `agent.disabled_toolsets`, the shared tool-assembly path (`model_tools._compute_tool_definitions`, used by the gateway, cron, AND the CLI) subtracted the WHOLE bundle from the enabled set. Because every platform bundle is defined as `_HERMES_CORE_TOOLS + [platform extras]`, and core tools are shared by every other enabled toolset, the subtraction emptied the tool list entirely — the model received `tools: []` / `tool_choice: null` and started replying "I cannot execute shell commands" with no error, no warning, and `hermes tools list` / `hermes doctor` still green. For unattended cron jobs this fails silently for days. (#33924) (The original report framed this as gateway-only; it actually affects every caller of `_compute_tool_definitions`, including the CLI — the reporter's follow-up confirms this. Fixing the shared chokepoint covers all paths.) Fix: for a `hermes-*` bundle in `disabled_toolsets`, subtract only its *non-core delta* (its platform-specific tools plus those of any `includes`), leaving `_HERMES_CORE_TOOLS` intact. Disabling a bundle now removes its platform tools (e.g. the `yb_*` tools for `hermes-yuanbao`) while terminal, read_file, web, etc. survive. A `logger.warning` notes that core tools are preserved and that bundle names usually belong in `toolsets:`, not `disabled_toolsets` — informative, not destructive (the subtraction still behaves sensibly). Salvaged from #33941 by @liuhao1024 (authorship preserved). Extracted the inline bundle-resolution into a module-level `_bundle_non_core_tools` helper (was re-importing `toolsets` inside the disable loop), and added the informative warning folding in the UX intent of #34073 (@ousiaresearch) without its hard "ignore the bundle name" behavior — which would have undone this fix's sensible-subtraction. Verified empirically: disabling `hermes-yuanbao` from a gateway-style enabled set keeps all core tools (18→18) and would remove only the 5 `yb_*` tools; disabling `hermes-discord` removes only `discord`/`discord_admin`. Fixes #33924 Co-authored-by: liuhao1024 <sunsky.lau@gmail.com>
This commit is contained in:
parent
7b9a0b315b
commit
dd042fc4df
3 changed files with 134 additions and 2 deletions
|
|
@ -34,6 +34,10 @@ from toolsets import resolve_toolset, validate_toolset
|
|||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Tracks platform-bundle names already flagged in disabled_toolsets so the
|
||||
# advisory (#33924) is logged once per name, not on every tool recompute.
|
||||
_WARNED_DISABLED_BUNDLES: set = set()
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Async Bridging (single source of truth -- used by registry.dispatch too)
|
||||
|
|
@ -392,8 +396,29 @@ def _compute_tool_definitions(
|
|||
if disabled_toolsets:
|
||||
for toolset_name in disabled_toolsets:
|
||||
if validate_toolset(toolset_name):
|
||||
resolved = resolve_toolset(toolset_name)
|
||||
tools_to_include.difference_update(resolved)
|
||||
if toolset_name.startswith("hermes-"):
|
||||
# Platform bundles (hermes-*) include _HERMES_CORE_TOOLS, so
|
||||
# subtracting the whole bundle would strip core tools shared
|
||||
# by other enabled toolsets and empty the tool list (#33924).
|
||||
# Subtract only the bundle's non-core delta; keep core.
|
||||
from toolsets import bundle_non_core_tools
|
||||
to_remove = bundle_non_core_tools(toolset_name)
|
||||
tools_to_include.difference_update(to_remove)
|
||||
resolved = sorted(to_remove)
|
||||
if not quiet_mode and toolset_name not in _WARNED_DISABLED_BUNDLES:
|
||||
_WARNED_DISABLED_BUNDLES.add(toolset_name)
|
||||
logger.info(
|
||||
"agent.disabled_toolsets contains platform-bundle "
|
||||
"name '%s'; core tools are preserved and only its "
|
||||
"platform-specific tools (%s) are removed. Bundle "
|
||||
"names usually belong in `toolsets:`, not "
|
||||
"`disabled_toolsets` (#33924).",
|
||||
toolset_name,
|
||||
", ".join(resolved) if resolved else "none",
|
||||
)
|
||||
else:
|
||||
resolved = resolve_toolset(toolset_name)
|
||||
tools_to_include.difference_update(resolved)
|
||||
if not quiet_mode:
|
||||
print(f"🚫 Disabled toolset '{toolset_name}': {', '.join(resolved) if resolved else 'no tools'}")
|
||||
elif toolset_name in _LEGACY_TOOLSET_MAP:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue