mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-30 20:17:47 +00:00
fix(toolsets): scope project tools to GUI sessions (off core)
project_list/create/switch were in _HERMES_CORE_TOOLS, so every platform (cli, cron, telegram, discord, …) shipped their schema on every API call — even though off the desktop the workspace callback no-ops and the DB write has no consumer (narrow waist). Drop them from _HERMES_CORE_TOOLS; they stay in the `project` toolset, which the desktop/TUI gateway folds into its resolved toolsets. _load_enabled_toolsets runs only in that gateway, so it's the gate that exposes them on exactly the surface that can follow a project move.
This commit is contained in:
@@ -722,9 +722,9 @@ def test_load_enabled_toolsets_rejects_disabled_mcp_env(monkeypatch, capsys):
|
||||
config_mod, "load_config", lambda: {"platform_toolsets": {"cli": ["memory"]}}
|
||||
)
|
||||
|
||||
# Sorted: ["kanban", "memory", "project"]. `kanban` and `project` are
|
||||
# auto-recovered by _get_platform_tools — both are non-configurable platform
|
||||
# toolsets whose tools live in hermes-cli's universe (see toolsets.py).
|
||||
# Sorted: ["kanban", "memory", "project"]. `kanban` is auto-recovered by
|
||||
# _get_platform_tools (a non-configurable platform toolset in hermes-cli's
|
||||
# universe); `project` is GUI-only, folded in by _load_enabled_toolsets.
|
||||
assert server._load_enabled_toolsets() == ["kanban", "memory", "project"]
|
||||
err = capsys.readouterr().err
|
||||
assert "ignoring disabled MCP servers" in err
|
||||
|
||||
@@ -5,10 +5,11 @@ Projects (per-profile ``projects.db``) are the named workspaces the desktop
|
||||
sidebar groups sessions into. Creating / switching a project is a deliberate act
|
||||
expressed as explicit tools — never a side effect of a terminal ``cd``.
|
||||
|
||||
Available everywhere (CLI, messaging, desktop) so projects can be triaged from
|
||||
any surface. The DB write is the durable part; when a GUI gateway has wired the
|
||||
workspace callback, a create/switch also re-anchors the live session's cwd so
|
||||
the sidebar follows the move. Elsewhere that step simply no-ops.
|
||||
Exposed only on GUI sessions: the tools live in the `project` toolset (kept off
|
||||
``_HERMES_CORE_TOOLS``) which the desktop/TUI gateway folds into its resolved
|
||||
toolsets, so no CLI/messaging/cron schema carries them. The GUI also wires
|
||||
``set_project_workspace_callback`` so a create/switch re-anchors the live
|
||||
session's cwd and the sidebar follows the move; the DB write is the durable part.
|
||||
"""
|
||||
|
||||
import json
|
||||
|
||||
10
toolsets.py
10
toolsets.py
@@ -51,9 +51,11 @@ _HERMES_CORE_TOOLS = [
|
||||
"text_to_speech",
|
||||
# Planning & memory
|
||||
"todo", "memory",
|
||||
# Desktop Projects (gateway-gated; the agent's intentional handle on the
|
||||
# sidebar's named workspaces)
|
||||
"project_list", "project_create", "project_switch",
|
||||
# NOTE: the desktop Project tools (project_list/create/switch) are
|
||||
# deliberately NOT here. They only make sense where a GUI can follow the
|
||||
# move, so they live in the `project` toolset and are enabled solely by the
|
||||
# GUI gateway (tui_gateway/server.py::_load_enabled_toolsets) — keeping them
|
||||
# off every CLI/messaging/cron schema (narrow waist).
|
||||
# Session history search
|
||||
"session_search",
|
||||
# Clarifying questions
|
||||
@@ -227,7 +229,7 @@ TOOLSETS = {
|
||||
},
|
||||
|
||||
"project": {
|
||||
"description": "Desktop Projects — create/switch named workspaces (gateway only)",
|
||||
"description": "Desktop Projects — create/switch named workspaces (GUI sessions only)",
|
||||
"tools": ["project_list", "project_create", "project_switch"],
|
||||
"includes": []
|
||||
},
|
||||
|
||||
@@ -2297,12 +2297,18 @@ def _load_enabled_toolsets() -> list[str] | None:
|
||||
# list without baking in implicit MCP defaults. Using the wrong
|
||||
# variant at agent creation time makes MCP tools silently missing
|
||||
# from the TUI. See PR #3252 for the original design split.
|
||||
enabled = sorted(
|
||||
_get_platform_tools(cfg, "cli", include_default_mcp_servers=True)
|
||||
)
|
||||
enabled = _get_platform_tools(cfg, "cli", include_default_mcp_servers=True)
|
||||
if fallback_notice is not None:
|
||||
print(fallback_notice, file=sys.stderr, flush=True)
|
||||
return enabled or None
|
||||
if not enabled:
|
||||
return None
|
||||
# The desktop Project tools are off _HERMES_CORE_TOOLS (every other
|
||||
# platform would carry their schema for nothing), so the platform
|
||||
# recovery above — which keys off hermes-cli's tool universe — can't
|
||||
# surface them. This resolver runs ONLY in the desktop/TUI gateway, so
|
||||
# folding in the `project` toolset here is the gate that exposes them on
|
||||
# exactly the surface that can follow a project move.
|
||||
return sorted(enabled | {"project"})
|
||||
except Exception:
|
||||
if fallback_notice is not None:
|
||||
print(
|
||||
|
||||
Reference in New Issue
Block a user