Reconciling agent.disabled_toolsets when enabling a toolset
Cluster 49995 · apps/desktop. Data as of
Nothing open on GitHub. Fix merged in #54334 on 28 Jun 2026. Check it covers your case.
The short answer
- Known?
- Yes. 3 related items grouped here, 1 issue already closed.
- Fix event
- A fix was merged to main in PR #54334. Check it covers your case. No release data is tracked.
- Tracker
- The maintainers' tracker marks this
resolved, deciding PR #54334. That is separate from the fix event. - Still open
- Nothing open on GitHub.
Members appear to concern one theme: enabling a toolset while it is listed in agent.disabled_toolsets. Two share the same title for a tools fix, and one bug report describes the Desktop Toolsets UI not re-enabling such a toolset and showing it as OFF on reopen.
Open issues0
Open PRs0
Fixes on record
-
#54334 fix(tools): reconcile agent.disabled_toolsets when a toolset is enabled
files:
hermes_cli/tools_config.py,tests/hermes_cli/test_tools_config.pyShow the diff
-
hermes_cli/tools_config.py@@ -1736,6 +1736,32 @@ def _save_platform_tools(config: dict, platform: str, enabled_toolset_keys: Set[ config.setdefault("known_plugin_toolsets", {}) config["known_plugin_toolsets"][platform] = sorted(plugin_keys) + # Reconcile with agent.disabled_toolsets. _get_platform_tools() applies + # that list as a final override AFTER reading platform_toolsets.<platform>, + # so a toolset listed there stays permanently OFF no matter what this + # function writes — the toggle "saves" but silently can't ever take + # effect. Blank Slate installs pre-populate this list with ~27 toolsets, + # making most of the desktop Toolsets UI unusable for re-enabling + # anything (issue #49995). + # + # Only toolsets the user just explicitly enabled FOR THIS PLATFORM are + # cleared from the global disabled list — toolsets the user did not + # touch (still unchecked) or that remain disabled on other platforms + # are left alone, so agent.disabled_toolsets keeps working as a + # cross-platform suppression list for anything not actively re-enabled. + agent_cfg = config.get("agent") + if isinstance(agent_cfg, dict): + disabled_toolsets = agent_cfg.get("disabled_toolsets") + if isinstance(disabled_toolsets, list) and disabled_toolsets: + newly_enabled = enabled_toolset_keys - preserved_entries + if newly_enabled: + remaining = [ + ts for ts in disabled_toolsets + if str(ts) not in newly_enabled + ] + if remaining != disabled_toolsets: + agent_cfg["disabled_toolsets"] = remaining + save_config(config) -
tests/hermes_cli/test_tools_config.py@@ -1676,3 +1676,83 @@ def test_vision_picker_custom_endpoint(tmp_path, monkeypatch): save_env.assert_called_once_with("OPENAI_API_KEY", "sk-secret") +def test_save_platform_tools_clears_newly_enabled_from_disabled_toolsets(): + """Enabling a toolset via the picker must remove it from + agent.disabled_toolsets, or _get_platform_tools() permanently masks it + back to OFF on the next read no matter what platform_toolsets says. + + Blank Slate installs pre-populate disabled_toolsets with ~27 toolsets, + making the desktop Toolsets UI's enable toggle effectively a no-op for + any of them (issue #49995). + """ + config = { + "platform_toolsets": {"cli": ["file", "terminal"]}, + "agent": {"disabled_toolsets": ["todo", "memory", "browser"]}, + } + + with patch("hermes_cli.tools_config.save_config"): + _save_platform_tools(config, "cli", {"file", "terminal", "todo"}) + + # The toolset the user just enabled is cleared from the block-list... + assert "todo" not in config["agent"]["disabled_toolsets"] + # ...but toolsets the user did NOT touch stay disabled (no over-reach). + assert "memory" in config["agent"]["disabled_toolsets"] + assert "browser" in config["agent"]["disabled_toolsets"] + assert "todo" in config["platform_toolsets"]["cli"] + + +def test_save_platform_tools_resolves_to_enabled_after_disabled_toolsets_reconcile(): + """End-to-end: after _save_platform_tools() reconciles disabled_toolsets, + _get_platform_tools() must actually resolve the toolset as enabled -- + this is the exact symptom from issue #49995 (toggle saves but the UI/agent + still reads it as OFF after reopen). + """ + config = { + "platform_toolsets": {"cli": ["file", "terminal"]}, + "agent": {"disabled_toolsets": ["todo", "memory"]}, + } + + # Before: todo is masked off despite not being in platform_toolsets yet. + assert "todo" not in _get_platform_tools(config, "cli") + + with patch("hermes_cli.tools_config.save_config"): + _save_platform_tools(config, "cli", {"file", "terminal", "todo"}) + + # After: todo must resolve as enabled, and untouched 'memory' must + # remain masked off. + resolved = _get_platform_tools(config, "cli") + assert "todo" in resolved + assert "memory" not in resolved + + +def test_save_platform_tools_no_disabled_toolsets_is_noop(): + """When agent.disabled_toolsets is absent or empty, the reconcile step + must be a complete no-op (no KeyError, no spurious 'agent' key creation). + """ + config = {"platform_toolsets": {"cli": ["file", "terminal"]}} + + with patch("hermes_cli.tools_config.save_config"): + _save_platform_tools(config, "cli", {"file", "terminal", "todo"}) + + assert "todo" in config["platform_toolsets"]["cli"] + # No 'agent' key should be fabricated when none existed. + assert "agent" not in config + + +def test_save_platform_tools_disabling_a_toolset_does_not_touch_disabled_toolsets(): + """Turning a toolset OFF (not present in enabled_toolset_keys) must not + remove anything from agent.disabled_toolsets -- only toolsets the user + just explicitly enabled are reconciled. + """ + config = { + "platform_toolsets": {"cli": ["file", "terminal", "todo"]}, + "agent": {"disabled_toolsets": ["memory"]}, + } + + with patch("hermes_cli.tools_config.save_config"): + # User unchecks 'todo' -- it's no longer in enabled_toolset_keys. + _save_platform_tools(config, "cli", {"file", "terminal"}) + + assert "todo" not in config["platform_toolsets"]["cli"] + # disabled_toolsets is untouched by a disable action. + assert config["agent"]["disabled_toolsets"] == ["memory"]
-
1 PR closed without merging
From the close comments: merged via another change 1
-
#50012 fix(tools): reconcile agent.disabled_toolsets when a toolset is enabled · merged via another change →
3e16176,#54334,#49995
Closed issues · 1
- Closed#49995[Bug]: Desktop Toolsets UI can't re-enable a toolset that's in agent.disabled_toolsets (Blank Slate); enabled toolsets revert to OFF on reopen
How this cluster was grouped
-
Link evidence (
structural links throughout): every member is connected by structural evidence: shared changed files, or a closing/superseded reference. -
Pairwise link density
0.67: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36.1.00means every pair is linked.
Pick up a Lab task
Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.
Open the LabAt a glance
- Subsystem
- apps/desktop
- Merged PRs
- #54334
- Closed issues
- 1
- Attempts
- 1 PR closed without merging
- Fix link checked
- 28 Jun 2026