10 Commits

Author SHA1 Message Date
teknium1
b5d7a7b15d fix(config): hermes doctor and plugins enable read a list-literal platform_toolsets string
#116691 taught the runtime (`_get_platform_tools`) to read the
`'["browser", "terminal"]'` string an older `hermes config set` stored as
the user's real toolset selection, but the two other readers of the section
kept the old `isinstance(raw, list)` gate:

- `validate_platform_toolsets` (hermes doctor / startup warnings) reported
  "invalid toolset value ... falling back to 'hermes-cli'" for a value the
  runtime resolves to browser+terminal — a false warning.
- `plugins_cmd._toggle_plugin_toolset` skipped the string entry, so
  `hermes plugins enable <p>` never reached that platform.
- `nous_subscription._toolset_enabled` treated it as an empty list.

Move the list-literal parse into one function,
`toolset_validation.parse_platform_toolsets_value`, and route all four
readers through it; the plugin toggle re-saves the entry as a real list so
the string never persists past the next write. `_coerce_platform_toolsets_value`
keeps its once-per-platform warning for values that do not parse.

Why one parser: three readers with three notions of "configured" is exactly
how #115866 went unnoticed. Follow-up to #116691 (independent review finding).
2026-09-20 12:44:48 -07:00
Teknium
fe8bfc1d68 refactor(hermes_cli): tools_config group — dense docstring reflow (word-identical, AST-verified) 2026-09-02 21:31:17 -07:00
Teknium
316427f215 refactor(hermes_cli): tools_config group — AST-neutral closer hugging and item packing (data tables kept expanded) 2026-09-02 21:22:11 -07:00
Teknium
3df6a09d62 refactor(hermes_cli): tools_config_post_setup/mcp/toolset_validation — shared _run_text, flattened branches 2026-09-02 20:48:27 -07:00
Teknium
f332d5b2ba refactor(hermes_cli): tools_config group — AST-neutral bracket hugging 2026-09-02 20:38:18 -07:00
Teknium
5d4b97939e refactor(hclib): config — config/config_migrations/tools_config/toolset_* dispatch tables and dedupe 2026-09-02 14:42:18 -07:00
phi hu
081030a7dd fix(config): warn for empty platform toolsets 2026-08-31 10:08:31 -07:00
phihu
ccd32a9f0b fix(config): warn when a platform_toolsets entry is an empty list
validate_platform_toolsets() accumulated a single valid_count across every
platform, so the "zero valid toolsets" safety net was suppressed as soon as any
one platform carried a valid toolset. A platform wiped to [] — the active one,
typically cli — therefore produced no warning at all.

resolve_enabled_toolsets() honours that empty list verbatim ([] is a list, so
the platform-default fallback is skipped), leaving the agent with zero tool
schemas. The model then has nothing to call and emits the tool call as
assistant text with finish_reason=stop: no error, no warning, no log entry.
That is the silent-failure mode this module was written to prevent (#38798).

Note the asymmetry this leaves intact: a malformed *string* value is not a list,
so it falls back to the platform default and fails open (#78103); an empty list
fails closed. The fail-closed resolution is deliberate (the explicit_empty_
selection contract in tools_config.py, and #82010 wants it persistable), so this
only adds the missing warning and does not change resolution semantics.

Fixes #89050

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-31 10:08:31 -07:00
teknium1
5b751dc0ad chore: remove unused imports and dead locals (ruff F401/F841 sweep)
Cleans F401 unused imports and F841 dead local assignments across
root *.py, agent/, hermes_cli/, tools/, gateway/, cron/, tui_gateway/
(tests/, plugins/, skills/ excluded).

Intentionally KEPT (false positives / test-patch surfaces):
- agent/transports/__init__.py package re-exports
- cli.py browser_connect re-exports (DEFAULT_BROWSER_CDP_URL area,
  used by tests/cli/test_cli_browser_connect.py)
- hermes_cli/main.py _prompt_auth_credentials_choice /
  _model_flow_bedrock_api_key (accessed via main_mod attr in tests)
- gateway/run.py aliased replay_cleanup + whatsapp_identity re-exports
  and _PORT_BINDING_PLATFORM_VALUES (test-referenced)
- hermes_cli/web_server.py get_running_pid (tests monkeypatch it) and
  _OAUTH_TOKEN_URL availability probe
- hermes_cli/config.py get_process_hermes_home re-export (noqa'd F811
  chain) and yaml availability-probe import
- hermes_cli/nous_subscription.py managed_nous_tools_enabled
  (tests patch hermes_cli.nous_subscription.managed_nous_tools_enabled)
- try/except ImportError availability probes (env_loader, tts_tool,
  mcp_tool, web_server anthropic OAuth block)
- tools/web_tools.py noqa F401 re-exports
- hermes_cli/setup_whatsapp_cloud.py:263 'proceed' skipped: possible
  missing-guard bug, flagged for separate review
- unused function parameters (signature changes out of scope)

Side-effect RHS calls preserved where only the binding was dead
(e.g. web_server proc = _spawn_hermes_action -> bare call).
2026-07-29 11:53:39 -07:00
lEWFkRAD
41ede84b93 fix(config): surface invalid platform_toolsets instead of silently dropping tools (#38798)
A config migration (or hand-edit) that leaves an invalid toolset name in
`platform_toolsets` — e.g. the #38798 corruption that rewrote `hermes-cli` to
the non-existent `hermes` — silently disabled all affected tools:
resolve_toolset() returns [] for an unknown name, so the agent quietly lost its
tools with no error, warning, or log entry and degraded to text-only replies.

Surface it loudly at two points:
- After migration (migrate_config): validate platform_toolsets and record/print
  a warning per unknown name, with a `hermes-<platform>` suggestion when that
  would have been valid (the exact #38798 shape).
- At runtime (_get_platform_tools): if a platform was explicitly configured but
  every toolset name is invalid, log a warning when tools are resolved for a
  session — so an ALREADY-corrupted config is caught at startup, not only on the
  next `hermes update`.

Logic lives in a new pure, side-effect-free helper (toolset_validation.py) with
validate_toolset injected, so it is unit-testable without the tool registry.

Note: the original v25→v26 migration that caused the corruption no longer
exists (config format is now v30; no migration step rewrites toolset names).
This change is the durable defense against the silent-failure mode regardless
of cause, matching the issue's "Expected: log a warning".

Salvaged from #39207 by @lEWFkRAD (authorship preserved via cherry-pick).
Tests: 9 helper cases (incl. the #38798 corruption shape, mixed valid/invalid,
zero-tools state, non-dict/scalar/non-string) + a runtime caplog test — both the
helper warning and the runtime guard mutation-verified to fail without the fix.

Closes #38798. Supersedes #39581 (prevent-in-v25→v26 — that path is gone),
#41006 / #40208 (repair-migration for already-corrupted configs).
2026-06-26 14:07:43 +05:30