mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-25 00:51:20 +00:00
revert: remove trailing empty assistant message stripping
Reverts the sanitizer addition from PR #2466 (originally #2129). We already have _empty_content_retries handling for reasoning-only responses. The trailing strip risks silently eating valid messages and is redundant with existing empty-content handling.
This commit is contained in:
parent
5407d12bc6
commit
34be3f8be6
8 changed files with 220 additions and 152 deletions
|
|
@ -23,12 +23,6 @@ Tool registration
|
|||
-----------------
|
||||
``PluginContext.register_tool()`` delegates to ``tools.registry.register()``
|
||||
so plugin-defined tools appear alongside the built-in tools.
|
||||
|
||||
Slash command registration
|
||||
--------------------------
|
||||
``PluginContext.register_command()`` adds a slash command to the central
|
||||
``COMMAND_REGISTRY`` so it appears in /help, autocomplete, and gateway
|
||||
dispatch. Handlers receive the argument string and return a response.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
|
@ -101,7 +95,6 @@ class LoadedPlugin:
|
|||
module: Optional[types.ModuleType] = None
|
||||
tools_registered: List[str] = field(default_factory=list)
|
||||
hooks_registered: List[str] = field(default_factory=list)
|
||||
commands_registered: List[str] = field(default_factory=list)
|
||||
enabled: bool = False
|
||||
error: Optional[str] = None
|
||||
|
||||
|
|
@ -148,45 +141,6 @@ class PluginContext:
|
|||
self._manager._plugin_tool_names.add(name)
|
||||
logger.debug("Plugin %s registered tool: %s", self.manifest.name, name)
|
||||
|
||||
# -- command registration ------------------------------------------------
|
||||
|
||||
def register_command(
|
||||
self,
|
||||
name: str,
|
||||
handler: Callable,
|
||||
description: str = "",
|
||||
aliases: tuple[str, ...] = (),
|
||||
args_hint: str = "",
|
||||
cli_only: bool = False,
|
||||
gateway_only: bool = False,
|
||||
) -> None:
|
||||
"""Register a slash command in the central command registry.
|
||||
|
||||
The *handler* is called with a single ``args`` string (everything
|
||||
after the command name) and should return a string to display to the
|
||||
user, or ``None`` for no output. Async handlers are also supported
|
||||
(they will be awaited in the gateway).
|
||||
|
||||
The command automatically appears in ``/help``, tab-autocomplete,
|
||||
Telegram bot menu, Slack subcommand mapping, and gateway dispatch.
|
||||
"""
|
||||
from hermes_cli.commands import CommandDef, register_plugin_command
|
||||
|
||||
cmd_def = CommandDef(
|
||||
name=name,
|
||||
description=description or f"Plugin command: {name}",
|
||||
category="Plugins",
|
||||
aliases=aliases,
|
||||
args_hint=args_hint,
|
||||
cli_only=cli_only,
|
||||
gateway_only=gateway_only,
|
||||
)
|
||||
register_plugin_command(cmd_def)
|
||||
self._manager._plugin_commands[name] = handler
|
||||
for alias in aliases:
|
||||
self._manager._plugin_commands[alias] = handler
|
||||
logger.debug("Plugin %s registered command: /%s", self.manifest.name, name)
|
||||
|
||||
# -- hook registration --------------------------------------------------
|
||||
|
||||
def register_hook(self, hook_name: str, callback: Callable) -> None:
|
||||
|
|
@ -218,7 +172,6 @@ class PluginManager:
|
|||
self._plugins: Dict[str, LoadedPlugin] = {}
|
||||
self._hooks: Dict[str, List[Callable]] = {}
|
||||
self._plugin_tool_names: Set[str] = set()
|
||||
self._plugin_commands: Dict[str, Callable] = {}
|
||||
self._discovered: bool = False
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
|
|
@ -372,14 +325,6 @@ class PluginManager:
|
|||
for h in p.hooks_registered
|
||||
}
|
||||
)
|
||||
loaded.commands_registered = [
|
||||
c for c in self._plugin_commands
|
||||
if c not in {
|
||||
n
|
||||
for name, p in self._plugins.items()
|
||||
for n in p.commands_registered
|
||||
}
|
||||
]
|
||||
loaded.enabled = True
|
||||
|
||||
except Exception as exc:
|
||||
|
|
@ -475,7 +420,6 @@ class PluginManager:
|
|||
"enabled": loaded.enabled,
|
||||
"tools": len(loaded.tools_registered),
|
||||
"hooks": len(loaded.hooks_registered),
|
||||
"commands": len(loaded.commands_registered),
|
||||
"error": loaded.error,
|
||||
}
|
||||
)
|
||||
|
|
@ -512,6 +456,46 @@ def get_plugin_tool_names() -> Set[str]:
|
|||
return get_plugin_manager()._plugin_tool_names
|
||||
|
||||
|
||||
def get_plugin_command_handler(name: str) -> Optional[Callable]:
|
||||
"""Return the handler for a plugin-registered slash command, or None."""
|
||||
return get_plugin_manager()._plugin_commands.get(name)
|
||||
def get_plugin_toolsets() -> List[tuple]:
|
||||
"""Return plugin toolsets as ``(key, label, description)`` tuples.
|
||||
|
||||
Used by the ``hermes tools`` TUI so plugin-provided toolsets appear
|
||||
alongside the built-in ones and can be toggled on/off per platform.
|
||||
"""
|
||||
manager = get_plugin_manager()
|
||||
if not manager._plugin_tool_names:
|
||||
return []
|
||||
|
||||
try:
|
||||
from tools.registry import registry
|
||||
except Exception:
|
||||
return []
|
||||
|
||||
# Group plugin tool names by their toolset
|
||||
toolset_tools: Dict[str, List[str]] = {}
|
||||
toolset_plugin: Dict[str, LoadedPlugin] = {}
|
||||
for tool_name in manager._plugin_tool_names:
|
||||
entry = registry._tools.get(tool_name)
|
||||
if not entry:
|
||||
continue
|
||||
ts = entry.toolset
|
||||
toolset_tools.setdefault(ts, []).append(entry.name)
|
||||
|
||||
# Map toolsets back to the plugin that registered them
|
||||
for _name, loaded in manager._plugins.items():
|
||||
for tool_name in loaded.tools_registered:
|
||||
entry = registry._tools.get(tool_name)
|
||||
if entry and entry.toolset in toolset_tools:
|
||||
toolset_plugin.setdefault(entry.toolset, loaded)
|
||||
|
||||
result = []
|
||||
for ts_key in sorted(toolset_tools):
|
||||
plugin = toolset_plugin.get(ts_key)
|
||||
label = f"🔌 {ts_key.replace('_', ' ').title()}"
|
||||
if plugin and plugin.manifest.description:
|
||||
desc = plugin.manifest.description
|
||||
else:
|
||||
desc = ", ".join(sorted(toolset_tools[ts_key]))
|
||||
result.append((ts_key, label, desc))
|
||||
|
||||
return result
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue