Commit Graph

12 Commits

Author SHA1 Message Date
Teknium d2672a349b feat(gateway): optional profile param on cron.manage RPC (#86796)
cron.manage resolved its jobs store from the process HERMES_HOME, so a profile
whose cron lives in ~/.hermes/profiles/<name>/cron/ was invisible to the default
gateway (and any bot/plugin querying per-profile routines saw 'no cron jobs').

Add an optional 'profile' param that scopes the whole action via
set_hermes_home_override, exactly mirroring the adjacent skills.manage handler:
resolve get_profile_dir(profile), 404 (err 4064) if missing, override in a
try/finally that always reset_hermes_home_override. Omitted/None keeps the
launch-profile behavior, so existing callers are unaffected. cronjob() itself is
unchanged (it already keys off HERMES_HOME).

Enables the Hermes-Bot-Mode plugin to show a bot's real routines
(NousResearch/Hermes-Bot-Mode#37). Needs a SERVE-backend gateway restart to take
effect live. 2/2 in the new focused test.

Co-authored-by: Teknium <teknium1@users.noreply.github.com>
2026-08-15 00:25:00 -07:00
Teknium d275b96bfd feat(gateway): per-profile MCP server lifecycle RPCs (mcp.servers.*) (#86473)
Adds the full MCP setup surface as profile-scoped gateway RPCs so a
desktop client (Bot Mode's bot editor, the core Capabilities tab) can
add/configure/test/authenticate/remove MCP servers for ANY profile, not
just the launch profile:

- mcp.servers.list (profile) -> configured servers (transport, auth,
  oauth_tokens_present, enabled, tool names; no secret values)
- mcp.servers.add (profile, name, config|preset, bearer_token?) -> reuses
  mcp_config._apply_mcp_preset / _save_mcp_server / _save_bearer_auth_token
- mcp.servers.set_api_key (profile, name, value, env_var?) -> http auth
  header template or stdio env ref, via save_env_value
- mcp.servers.test (profile, name) -> _probe_single_server + oauth state
- mcp.servers.remove (profile, name)
- mcp.servers.oauth.start/poll (profile, name[, session_id]) -> mirrors the
  PROVIDER oauth session/poll model (not the FastAPI dashboard flow): a
  background worker drives the same interactive machinery 'hermes mcp login'
  uses, capturing the browser redirect on a local loopback listener. Client
  opens auth_url via openExternal and polls until status=='approved'.

All handlers are profile-scoped via set_hermes_home_override in try/finally
(mirrors skills.manage). Shared helpers live in tui_gateway/mcp_rpc_helpers.py
and are aliased onto server.py's namespace so the rebound handler bodies
(HandlerRegistry.install) can resolve them — a plain def in methods_tools is
unreachable post-rebind. Reuses hermes_cli/mcp_config.py throughout; no config
logic duplicated; no raw yaml near config.yaml (config-read-guard safe).

Tests: tests/tui_gateway/test_mcp_profile_rpcs.py, 8 E2E against real temp
HERMES_HOME profiles asserting add/list/set_api_key/remove land in the RIGHT
profile's config.yaml and not the launch profile's. 8/8. Registration +
live mcp.servers.list verified in an imported gateway.

Co-authored-by: Teknium <teknium1@users.noreply.github.com>
2026-08-14 16:17:22 -07:00
teknium1 f79440e0f4 feat: /loop — recurring in-session wakeups (Claude Code parity)
Ports Claude Code's /loop (and its /proactive alias) across every Hermes
surface. /loop [interval] <prompt> re-runs a prompt or slash command on a
recurring cadence inside the live session; omitting the interval enables
self-paced mode (starts at the floor, backs off exponentially while the
agent's replies stop changing, snaps back on change — local digest
comparison, zero extra LLM cost).

Stop conditions: agent-emitted LOOP_COMPLETE marker, --times N,
--until <condition> (judged by the existing goal_judge aux task,
fail-open), /loop stop, and a loops.max_ticks backstop budget.

Core: hermes_cli/loops.py (LoopState + LoopManager + shared
dispatch_loop_command), persisted per session in SessionDB state_meta
(loop:<sid>) so /resume picks it up; migrates across compression
boundaries like /goal. New SessionDB.list_meta_prefix() powers the
gateway's cross-session scan.

Surfaces:
- CLI: /loop handler + idle-fire and post-turn-complete hooks in
  process_loop (mirrors the /goal hook shape; Ctrl+C pauses the loop)
- Gateway: /loop handler with route capture, mid-run control-verb guard,
  post-turn tick completion, and a supervised loop_wakeup_watcher that
  injects due wakeups into idle chats via the synthetic-message path
- TUI/dashboard/desktop: command.dispatch handler + per-session
  notification-poller wakeup driver + post-turn completion in the turn
  dispatcher; /loop added to the desktop slash palette
- /goal mixing: an active non-parked goal owns the idle boundary — loop
  ticks defer until it finishes, pauses, or parks; real user input always
  wins over both

Config: loops.{min_interval_seconds,max_ticks,self_paced_floor_seconds,
self_paced_ceiling_seconds}. Docs page + sidebar entry. 77 new tests.
Slack's 50-slash cap: /version moves to /hermes version to free the
native slot for /loop.
2026-08-14 13:40:19 -07:00
Teknium cc1c125cf3 fix(gateway): honest capability surfaces for profile editors (#86227)
Three fixes for what profiles.describe & friends expose (tester
report with screenshot):

1. describe's toolsets used the RAW registry (get_all_toolsets) —
   leaking internal platform composites (hermes-discord, hermes-cron,
   feishu_drive, discord_admin, desktop_ui, ...) that are gated,
   platform-restricted, or deliberately hidden from users — and
   reported everything enabled whenever the profile had no pin.
   Now: the same filtered universe the `hermes tools` checklist
   offers (_get_effective_configurable_toolsets, platform-filtered),
   with enablement resolved via _get_platform_tools like the runtime.

2. skills.manage accepts optional `profile`: list/install scoped to
   that profile's skills dir via the home override, so editors can
   manage a bot's skills (incl. hub installs) from the main window.
   search/browse/inspect (the hub catalog) unchanged.

3. New mcp.catalog method: the bundled MCP catalog with per-profile
   installed/enabled state + required env keys, so capability UIs can
   offer the full menu and route un-setup entries through setup
   instead of silently listing dead servers.

E2E: describe now returns only user-facing toolsets with honest
enabled flags; mcp.catalog returns the 5-entry catalog; skills list
scopes to the named profile.
2026-08-14 10:29:43 -07:00
Teknium a364390dab feat: forward repeat through cron.manage add (#85602)
cronjob(action=create) has supported a repeat cap since the tool
existed, but the ws handler dropped the param — UIs building on
cron.manage could not create run-N-times jobs. Forward it (digit
strings accepted, None keeps schedule-kind defaults). One-shot
relative schedules (bare 30m/2h) already flow through the schedule
string untouched.
2026-08-13 13:14:57 -07:00
Teknium dcbfc79f8d fix: forward include_disabled through cron.manage list (#85566)
cronjob(action=list) defaults to include_disabled=False, so pausing a
job makes it vanish from any ws-driven UI's next refresh — an
enable/disable toggle reads as silent deletion (reported against the
Hermes-Bot-Mode routines pane). Forward the flag from params.
2026-08-13 12:14:33 -07:00
Brooklyn Nicholson ed9eee5dc9 fix(gateway): report bundled auto-loading plugins as enabled
Bundled backends/platforms/providers load without a plugins.enabled
entry ('must just work'), but plugins.manage reported them 'not
enabled' — clients rendered running plugins with an OFF switch.
Surface the truthful default; explicit disable still wins.
2026-08-08 17:34:20 -05:00
Brooklyn Nicholson a60b492e07 feat(gateway): key-addressed plugins.manage rows + portable MCP toolset fold-in
plugins.manage list rows now carry the canonical registry key and a
portable flag (Agent Plugins v1 plugin.json packages), and toggles
address the key — bare names collide across category dirs
(image_gen/fal vs video_gen/fal), so name-addressed toggles flipped
both. Portable packages' in-memory MCP servers also fold into
enabled_mcp_server_names(); without that their tools registered with
the MCP runtime but never reached the model's schema.
2026-08-08 17:24:59 -05:00
kshitij 4eabb595f0 fix(agent): finish the #80622 bug class — sibling predicates, refund ordering, prompt carve-out, honest skip response
Follow-ups on top of the salvaged #80696 fix (review findings):

- Sibling sites: rollback.restore, gateway /retry, CLI /retry and /undo N,
  and both CLI resume turn counters now use is_user_originated_turn so
  legacy-persisted standalone handoffs (durable role=user, no display_kind)
  can never be truncation targets or counted as user turns (#80622
  suggested regression 4, dispatcher-wide).
- Site-1 guard: hoist the api_call_count decrement + iteration-budget
  refund above the break so a skipped turn no longer leaks a budget unit
  and finalize_turn logs the true call count (matches the ollama early-exit
  and the site-2 sibling).
- Site-2 guard: run the handoff guard BEFORE reanchoring so a restored
  user ask is what the anchor lands on, not a stale pre-restore index.
- SUMMARY_PREFIX: add the mid-tool-loop carve-out the code-side guard
  already implements, so a literal-minded model doesn't halt an in-flight
  exchange after in-place compaction.
- Skip path returns a short compaction status instead of replaying the
  previous turn's answer (finalize_turn would append it as a fresh
  assistant row — duplicate prose in transcript and delivery).
2026-08-07 19:44:35 +05:30
HexLab98 6d3ff6eda8 fix(agent): stop reference-only compaction handoff from becoming the active turn
After a completed assistant stop, a standalone CONTEXT COMPACTION handoff
could occupy the sole user slot and resume stale Historical Task Snapshot
work with no new human ask. Guard post-compaction continues, hide
standalone handoffs from session dispatch, and harden SUMMARY_PREFIX for
the empty-after-handoff case (#80622).
2026-08-07 19:44:35 +05:30
Teknium ebd61ce5ac fix(secrets): scope tier-3 credential reads (teams_pipeline, deepinfra models, FAL/XAI/VERCEL/DAYTONA/GITHUB presence, HERMES_API_KEY display)
NOTION_API_KEY/LINEAR_API_KEY defaults, DEEPINFRA_API_KEY model gate, FAL_KEY via the file's own _scoped_credential helper, XAI/VERCEL/DAYTONA presence checks, GITHUB_TOKEN/GH_TOKEN + GitHub App creds in tirith/skills_hub, and the masked HERMES_API_KEY display in tui_gateway config.show all route through get_secret.
2026-08-02 10:04:48 -07:00
teknium1 f67ca220ab refactor(tui): split @method handlers into methods_* modules (mechanical move, registry set-equality verified) 2026-07-29 11:46:31 -07:00