From 782d0219a0a3c475882b2dae0dca7d8d80eecf0a Mon Sep 17 00:00:00 2001 From: virtuadex <207573629+virtuadex@users.noreply.github.com> Date: Mon, 27 Jul 2026 04:06:27 +0100 Subject: [PATCH] docs: sync overnight sweep with registry, gateway, curator, cron MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Salvaged from #72422 by @virtuadex (conflicts resolved against current main; superseded slash-command hunks dropped): - SECURITY.md + SECURITY.es.md: gateway adapters live under plugins/platforms//, registry in gateway/platform_registry.py - gateway-internals.md (EN + zh-Hans): key-files table rows for platform_registry.py and plugins/platforms/, deferred-loading section - slash-commands.md: /reasoning full level list (max/ultra) + --global; CLI-only notes list gains /prompt, /pet, /hatch, /timestamps - cron.md + cron-script-only.md: script runner accuracy — bash resolved from PATH with /bin/bash fallback, script paths confined to ~/.hermes/scripts/, provider credentials stripped via _sanitize_subprocess_env - curator.md: cron-referenced skills protected from auto-archive, never-used grace floor --- SECURITY.es.md | 10 +++++++--- SECURITY.md | 9 ++++++--- .../docs/developer-guide/gateway-internals.md | 6 +++++- website/docs/guides/cron-script-only.md | 2 +- website/docs/reference/slash-commands.md | 20 ++++++++++++++++--- website/docs/user-guide/features/cron.md | 2 +- website/docs/user-guide/features/curator.md | 4 ++++ .../developer-guide/gateway-internals.md | 4 +++- 8 files changed, 44 insertions(+), 13 deletions(-) diff --git a/SECURITY.es.md b/SECURITY.es.md index 30b43716ebb..086656d4f73 100644 --- a/SECURITY.es.md +++ b/SECURITY.es.md @@ -173,9 +173,13 @@ modelo de autorización, pero las reglas a continuación se aplican uniformement **Superficies en Hermes Agent:** -- **Adaptadores de plataforma del gateway.** Integraciones de mensajería en - `gateway/platforms/` (Telegram, Discord, Slack, email, SMS, etc.) - y adaptadores análogos incluidos como plugins. +- **Adaptadores de plataforma del gateway.** La mayoría de las integraciones + de mensajería se distribuyen como plugins empaquetados en + `plugins/platforms//` (Telegram, Discord, Slack, email, SMS, etc.). + Los tipos base compartidos y un conjunto menor de adaptadores + legacy/directos viven en `gateway/platforms/` (`base.py`, Signal, servidor + API, webhooks, …), con descubrimiento y carga diferida vía + `gateway/platform_registry.py`. - **Superficies HTTP expuestas en red.** El adaptador del servidor API, el plugin del dashboard, los endpoints HTTP del plugin kanban, y cualquier otro plugin que vincule un socket de escucha. diff --git a/SECURITY.md b/SECURITY.md index 2579c6eaec5..7f5fd42db7b 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -177,9 +177,12 @@ authorization model, but the rules below apply uniformly. **Surfaces in Hermes Agent:** -- **Gateway platform adapters.** Messaging integrations in - `gateway/platforms/` (Telegram, Discord, Slack, email, SMS, etc.) - and analogous adapters shipped as plugins. +- **Gateway platform adapters.** Most messaging integrations ship as + bundled plugins under `plugins/platforms//` (Telegram, Discord, + Slack, email, SMS, etc.). Shared base types and a smaller set of + legacy/direct adapters live under `gateway/platforms/` + (`base.py`, Signal, API server, webhooks, …), with discovery and + deferred loading via `gateway/platform_registry.py`. - **Network-exposed HTTP surfaces.** The API server adapter, the dashboard plugin, the kanban plugin's HTTP endpoints, and any other plugin that binds a listening socket. diff --git a/website/docs/developer-guide/gateway-internals.md b/website/docs/developer-guide/gateway-internals.md index b4eebf279c3..30c8cb9e1f0 100644 --- a/website/docs/developer-guide/gateway-internals.md +++ b/website/docs/developer-guide/gateway-internals.md @@ -21,7 +21,9 @@ The messaging gateway is the long-running process that connects Hermes to 20+ ex | `gateway/mirror.py` | Cross-session message mirroring for `send_message` | | `gateway/status.py` | Token lock management for profile-scoped gateway instances | | `gateway/builtin_hooks/` | Extension point for always-registered hooks (none shipped) | -| `gateway/platforms/` | Platform adapters (one per messaging platform) | +| `gateway/platform_registry.py` | Adapter registry, factories, and deferred (lazy) loaders for bundled platform plugins | +| `plugins/platforms//` | Bundled messaging adapters (most platforms: `adapter.py` + `plugin.yaml`) | +| `gateway/platforms/` | Shared `base.py` plus legacy/direct adapters (Signal, API server, webhooks, …) | ## Architecture Overview @@ -176,6 +178,8 @@ gateway/platforms/ # core base + legacy direct adapters └── api_server.py # REST API server adapter ``` +**Deferred loading:** Bundled `kind: platform` plugins register cheap `register_deferred` loaders in `gateway/platform_registry.py` (via `hermes_cli/plugins.py`) so platform SDKs import only when the gateway starts, delivers, or runs setup/status — not on plain `hermes chat`. Resolution loads one adapter on lookup; full enumeration runs pending loaders only on paths that need every platform. + Experimental connector-backed platforms use the generic relay adapter in `gateway/relay/` instead of a direct platform module. When `GATEWAY_RELAY_URL` or `gateway.relay_url` is configured, the gateway registers the `relay` platform, dials the connector over an outbound WebSocket, and receives `descriptor`, `inbound`, and `interrupt_inbound` frames on that same socket. The connector advertises a `CapabilityDescriptor`; Hermes can send normal outbound replies, token-less `follow_up` operations, and interrupt frames back through the relay. The source-grounded wire contract lives in [`docs/relay-connector-contract.md`](https://github.com/NousResearch/hermes-agent/blob/main/docs/relay-connector-contract.md). Adapters implement a common interface: diff --git a/website/docs/guides/cron-script-only.md b/website/docs/guides/cron-script-only.md index 04051ddd23e..3488bf9e71c 100644 --- a/website/docs/guides/cron-script-only.md +++ b/website/docs/guides/cron-script-only.md @@ -28,7 +28,7 @@ Hermes calls this **no-agent mode**. It's the cron system minus the LLM. - **No LLM call.** Zero tokens, zero agent loop, zero model spend. - **Script is the job.** The script decides whether to alert. Emit output → message gets sent. Emit nothing → silent tick. -- **Bash or Python.** `.sh` / `.bash` files run under `/bin/bash`; any other extension runs under the current Python interpreter. Anything in `~/.hermes/scripts/` is accepted. +- **Bash or Python.** `.sh` / `.bash` files run under `bash` from `PATH` when available, otherwise `/bin/bash`; any other extension runs under the current Python interpreter. Paths must resolve inside `~/.hermes/scripts/` (relative, absolute, or `~` forms are OK if they stay in that directory). Cron scripts do **not** inherit provider credentials from the Hermes process environment. - **Same scheduler.** Lives in `cronjob` alongside LLM jobs — pausing, resuming, listing, logs, and delivery targeting all work the same way. ## When to Use It diff --git a/website/docs/reference/slash-commands.md b/website/docs/reference/slash-commands.md index 0a4c9905aaa..f299ee6c151 100644 --- a/website/docs/reference/slash-commands.md +++ b/website/docs/reference/slash-commands.md @@ -63,6 +63,7 @@ Type `/` in the CLI to open the autocomplete menu. Built-in commands are case-in | `/agents` (alias: `/tasks`) | Show active agents and running tasks across the current session. | | `/background ` (alias: `/bg`, `/btw`) | Run a prompt in a separate background session. The agent processes your prompt independently — your current session stays free for other work. Results appear as a panel when the task finishes. See [CLI Background Sessions](/user-guide/cli#background-sessions). | | `/branch [name]` (alias: `/fork`) | Branch the current session (explore a different path) | +| `/journey [list\|delete \|edit ]` (aliases: `/learning`, `/memory-graph`) | **CLI only.** Open the learning journey timeline. | | `/handoff ` | **CLI only.** Hand the current session off to a messaging platform (Telegram, Discord, Slack, WhatsApp, Signal, Matrix). The gateway picks it up immediately, creates a fresh thread on platforms that support threads (Telegram topics, Discord text-channel threads, Slack message-anchored threads), re-binds the destination to your CLI session_id so the full role-aware transcript replays, and forges a synthetic user turn so the agent confirms it's working in the new place. Your CLI exits cleanly on success with a `/resume` hint; resume locally any time with `/resume `. Refused mid-turn. Requires the gateway to be running and a home channel configured for the target platform (`/sethome` from the destination chat). See [Cross-Platform Handoff](/user-guide/sessions#cross-platform-handoff). | | `/journey [list\|delete <id>\|edit <id>]` (aliases: `/learning`, `/memory-graph`) | Open the learning journey timeline of learned skills + memories. Works in the classic CLI, as a TUI overlay, and in the desktop app (Star Map panel). Not available on messaging platforms. See [Learning Journey](/user-guide/features/memory#learning-journey-journey). | @@ -77,7 +78,7 @@ Type `/` in the CLI to open the autocomplete menu. Built-in commands are case-in | `/verbose` | Cycle tool progress display: off → new → all → verbose. Can be [enabled for messaging](#notes) via config. | | `/focus [on\|off\|status]` | Toggle **focus view** — a display-only reduced-output mode showing just your prompt and the final response. Composes with `/verbose`: turning it on snaps tool progress to `off` and remembers your previous mode, and `/focus off` restores it. Each turn ends with a dim recovery line (`⋯ 7 tool lines hidden · /focus off to show`) and a persistent `◉ focus` badge sits in the status bar so you always know you're in the reduced view. Nothing is sent differently to the model — detail is hidden, never discarded. | | `/fast [normal\|fast\|status]` | Toggle fast mode — OpenAI Priority Processing / Anthropic Fast Mode. Options: `normal`, `fast`, `status`. | -| `/reasoning` | Manage reasoning effort and display (usage: /reasoning [level\|show\|hide]) | +| `/reasoning [level\|show\|hide\|full\|clamp] [--global]` | Manage reasoning effort and display. Levels include `none` / `minimal` / `low` / `medium` / `high` / `xhigh` / `max` / `ultra`. `show` / `hide` (or `on` / `off`) toggle reasoning display; `full` and `clamp` adjust how reasoning is shown. `--global` persists effort to config. | | `/skin` | Show or change the display skin/theme | | `/statusbar` (alias: `/sb`) | Toggle the context/model status bar on or off | | `/battery [on\|off\|status]` | Toggle a color-coded battery read-out as the first status-bar element (off by default; no-op without a battery). | @@ -125,6 +126,7 @@ Type `/` in the CLI to open the autocomplete menu. Built-in commands are case-in | `/topup` | Show your Nous balance and manage billing on the portal (replaces the old `/credits` and `/billing` commands). | | `/subscription` (alias: `/upgrade`) | **CLI only.** View your Nous plan and change it in the browser. | | `/insights` | Show usage insights and analytics (last 30 days) | +| `/update` | Update Hermes Agent to the latest version. | | `/platforms` (alias: `/gateway`) | Show gateway/messaging platform status (CLI-only summary view). | | `/paste` | Attach a clipboard image | | `/copy [number]` | Copy the last assistant response to clipboard (or the Nth-from-last with a number). CLI-only. | @@ -238,7 +240,7 @@ The messaging gateway supports the following built-in commands inside Telegram, | `/topup` | Show your Nous balance and manage billing on the portal. | | `/whoami` | Show your slash command access level (admin / user). | | `/insights [days]` | Show usage analytics. | -| `/reasoning [level\|show\|hide]` | Change reasoning effort or toggle reasoning display. | +| `/reasoning [level\|show\|hide\|full\|clamp] [--global]` | Change reasoning effort (levels up to `max` / `ultra`) or toggle reasoning display (`full` / `clamp` included). `--global` persists to config. | | `/voice [on\|off\|tts\|join\|channel\|leave\|status]` | Control spoken replies in chat. `join`/`channel`/`leave` manage Discord voice-channel mode. | | `/rollback [number]` | List or restore filesystem checkpoints. | | `/diff [staged\|all\|session] [--stat]` | Show git changes in the working directory (fenced and truncated to platform message limits). `session` shows the cumulative diff of everything Hermes changed; `--stat` shows just the summary. | @@ -246,6 +248,17 @@ The messaging gateway supports the following built-in commands inside Telegram, | `/queue <prompt>` (alias: `/q`) | Queue a prompt for the next turn without interrupting the current one. | | `/steer <prompt>` | Inject a message after the next tool call without interrupting — the model picks it up on its next iteration rather than as a new turn. | | `/goal <text>` | Set a standing goal Hermes works toward across turns — our take on the Ralph loop. A judge model checks after each turn; if not done, Hermes auto-continues until it is, you pause/clear it, or the turn budget (default 20) is hit. Subcommands: `/goal status`, `/goal pause`, `/goal resume`, `/goal clear`. Safe to run mid-agent for status/pause/clear; setting a new goal requires `/stop` first. See [Persistent Goals](/user-guide/features/goals). | +| `/subgoal <text>` | Append criteria to the active `/goal` mid-loop (`/subgoal`, `/subgoal remove <N>`, `/subgoal clear`). | +| `/moa <prompt>` | Run one prompt through the default [Mixture of Agents](/user-guide/features/mixture-of-agents) preset, then restore the session model. | +| `/branch [name]` (alias: `/fork`) | Branch the current session (explore a different path). | +| `/agents` (alias: `/tasks`) | Show active agents and running tasks. | +| `/sessions` | Browse and resume previous sessions. | +| `/context [all]` (alias: `/ctx`) | Context-window usage gauge and category breakdown (messaging-friendly text form). `/context all` adds per-skill / per-toolset cost detail. | +| `/egress [status]` | Show Docker egress proxy status. | +| `/init [notes]` | Generate or update `AGENTS.md` from a repo scan. | +| `/learn <what to learn from>` | Distill a reusable skill from anything you describe. | +| `/bundles` | List configured skill bundles (`/<name>` aliases that preload several skills). | +| `/reload-skills` (alias: `/reload_skills`) | Re-scan `~/.hermes/skills/` for newly installed or removed skills. | | `/footer [on\|off\|status]` | Toggle the runtime-metadata footer on final replies (shows model, context %, and cwd). | | `/curator [status\|run\|pin\|archive]` | Background skill maintenance controls. | | `/suggestions [accept\|dismiss N\|catalog\|clear]` | Review suggested automations right in chat. `/suggestions` lists pending suggestions, `catalog` adds curated starter automations, and `clear` prunes resolved suggestion records. Accepted suggestions keep this chat/thread as the job delivery origin. | @@ -255,6 +268,7 @@ The messaging gateway supports the following built-in commands inside Telegram, | `/kanban <action>` | Drive the multi-profile, multi-project collaboration board from chat — identical argument surface to the CLI. Bypasses the running-agent guard, so `/kanban unblock t_abc`, `/kanban comment t_abc "…"`, `/kanban list --mine`, `/kanban boards switch <slug>`, etc. work mid-turn. `/kanban create …` auto-subscribes the originating chat to the new task's terminal events. See [Kanban slash command](/user-guide/features/kanban#kanban-slash-command). | | `/platform <list\|pause\|resume> [name]` | Operate a running gateway platform right from chat. `/platform list` shows every adapter and its state (running, paused-by-breaker, manually-paused); `/platform pause <name>` stops dispatching new messages to that adapter without unloading it; `/platform resume <name>` re-enables it and clears a tripped circuit breaker once the upstream is healthy. | | `/reload-mcp` (alias: `/reload_mcp`) | Reload MCP servers from config. | +| `/verbose` | Cycle tool progress display. **Off by default on messaging** — enable with `display.tool_progress_command: true` in `config.yaml`. | | `/yolo` | Toggle YOLO mode — skip all dangerous command approval prompts. | | `/commands [page]` | Browse all commands and skills (paginated). | | `/approve [session\|always]` | Approve and execute a pending dangerous command. `session` approves for this session only; `always` adds to permanent allowlist. | @@ -267,7 +281,7 @@ The messaging gateway supports the following built-in commands inside Telegram, ## Notes -- `/skin`, `/snapshot`, `/reload`, `/tools`, `/toolsets`, `/browser`, `/config`, `/cron`, `/platforms`, `/paste`, `/image`, `/statusbar`, `/battery`, `/focus`, `/plugins`, `/busy`, `/indicator`, `/wake`, `/journey`, `/redraw`, `/clear`, `/history`, `/save`, `/copy`, `/handoff`, `/subscription`, and `/quit` are **CLI-only** commands. +- `/skin`, `/snapshot`, `/reload`, `/tools`, `/toolsets`, `/browser`, `/config`, `/cron`, `/platforms`, `/paste`, `/image`, `/statusbar`, `/battery`, `/focus`, `/plugins`, `/busy`, `/indicator`, `/wake`, `/journey`, `/redraw`, `/clear`, `/history`, `/save`, `/copy`, `/handoff`, `/prompt`, `/pet`, `/hatch`, `/timestamps`, `/subscription`, and `/quit` are **CLI-only** commands. - `/skills` is **CLI-only for search/browse/install**; its write-approval review subcommands (`pending`, `approve`, `reject`, `diff`, `approval`) also work on messaging platforms when `skills.write_approval` is on. `/memory` works on **both** surfaces. - `/verbose` is **CLI-only by default**, but can be enabled for messaging platforms by setting `display.tool_progress_command: true` in `config.yaml`. When enabled, it cycles the `display.tool_progress` mode and saves to config. - `/focus` and `/verbose` share one suppression path (`display.tool_progress`), so they can never contradict each other: `/focus on` pins tool progress to `off` and stashes your mode under `display.focus_saved_tool_progress`; `/focus off` restores it; cycling `/verbose` while focus is on takes the mode back and clears the focus badge. Focus view is display-only — it never changes conversation history, the system prompt, or anything sent to the model, so it has zero prompt-cache impact. diff --git a/website/docs/user-guide/features/cron.md b/website/docs/user-guide/features/cron.md index 87588b3ccc7..b855f5e5ec5 100644 --- a/website/docs/user-guide/features/cron.md +++ b/website/docs/user-guide/features/cron.md @@ -480,7 +480,7 @@ Semantics: - `{"wakeAgent": false}` on the last line → silent tick (same gate LLM jobs use). - No tokens, no model, no provider fallback — the job never touches the inference layer. -`.sh` / `.bash` files run under `/bin/bash`; anything else under the current Python interpreter (`sys.executable`). Scripts must live in `~/.hermes/scripts/` (same sandboxing rule as the pre-run script gate). +`.sh` / `.bash` files run under `bash` from `PATH` when available, otherwise `/bin/bash` (important on Windows Git Bash). Anything else runs under the current Python interpreter (`sys.executable`). Scripts must resolve inside `$HERMES_HOME/scripts/` — relative names, absolute paths, and `~`-prefixed paths are accepted when the resolved target stays in that directory; paths that escape it are rejected. Subprocess env is sanitized (`_sanitize_subprocess_env`): provider API credentials and other Hermes-managed secrets are **not** inherited by cron scripts. ### The agent sets these up for you diff --git a/website/docs/user-guide/features/curator.md b/website/docs/user-guide/features/curator.md index 1d5b1933f28..853e4205acd 100644 --- a/website/docs/user-guide/features/curator.md +++ b/website/docs/user-guide/features/curator.md @@ -32,6 +32,8 @@ If you want to see what the curator *would* do before it runs for real, run `her A run has two phases: 1. **Automatic transitions** (deterministic, no LLM). Skills unused for `stale_after_days` (30) become `stale`; skills unused for `archive_after_days` (90) are moved to `~/.hermes/skills/.archive/`. This is the always-on pruning behavior — it runs whenever the curator is enabled, with no aux-model cost. + - **Pinned skills** and **skills referenced by any cron job** (including paused/disabled jobs) are skipped entirely — treated like pin for auto-transitions so a slow or paused schedule cannot archive a skill out from under a job. Consolidation also rewrites cron skill references when it merges umbrellas. + - **Never-used skills** (`use_count == 0`) get a grace floor: they are not archived until they are at least `stale_after_days` old. Zero uses is absence of evidence, not proof the skill is disposable. 2. **LLM consolidation** (single aux-model pass with a high iteration ceiling — a full curation sweep typically takes 50–100 API calls) — **OFF by default**. When `curator.consolidate: true`, the forked agent surveys the agent-created skills, can read any of them with `skill_view`, and decides per-skill whether to keep, patch (via `skill_manage`), consolidate overlapping ones into class-level umbrellas, or archive via the terminal tool. Consolidation treats a skill as a full package: if a skill has `references/`, `templates/`, `scripts/`, `assets/`, or relative links to those paths, the curator must either keep it standalone, re-home the needed support files and rewrite paths, or archive the entire package unchanged — not flatten only `SKILL.md` into another skill's `references/` file. :::info Consolidation is opt-in @@ -266,6 +268,8 @@ hermes curator unpin <skill> The flag is stored as `"pinned": true` on the skill's entry in `~/.hermes/skills/.usage.json`, so it survives across sessions. +Skills named in any cron job's `skills:` list are protected the same way for **auto-transitions** (the curator never stales/archives them while the reference remains), even when the job is paused or disabled. Prefer an explicit pin when you also want `skill_manage delete` blocked. + Only **agent-created** skills can be pinned — `hermes curator pin` refuses on bundled and hub-installed skills with an explanatory message if you try. Hub-installed skills are never subject to curator mutation. Bundled built-in skills are only touched when `curator.prune_builtins: true` (the default), and even then only archived after `archive_after_days` of non-use — never patched, consolidated, or deleted. Set `curator.prune_builtins: false` to exempt bundled skills entirely. A small set of **protected built-ins** is hardcoded as never-archivable and never-consolidatable, regardless of `curator.prune_builtins`, pin state, or LLM judgment. These back load-bearing UX — for example, `plan` powers the `/plan` slash-command flow — so silently archiving one would turn its slash command into an "Unknown command" error with no signal to you. Protected built-ins are filtered out of the curator's candidate list entirely, so the consolidation pass never sees them. diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/developer-guide/gateway-internals.md b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/developer-guide/gateway-internals.md index 63c89d7e802..e560e44b4c6 100644 --- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/developer-guide/gateway-internals.md +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/developer-guide/gateway-internals.md @@ -21,7 +21,9 @@ description: "消息 gateway 如何启动、授权用户、路由会话以及投 | `gateway/mirror.py` | 为 `send_message` 提供跨会话消息镜像 | | `gateway/status.py` | 面向 profile 范围的 gateway 实例的 token 锁管理 | | `gateway/builtin_hooks/` | 始终注册的 hook 扩展点(当前未内置任何 hook) | -| `gateway/platforms/` | 平台适配器(每个消息平台一个) | +| `gateway/platform_registry.py` | 适配器注册表、工厂,以及对捆绑平台插件的延迟(惰性)加载 | +| `plugins/platforms/<name>/` | 捆绑的消息适配器(多数平台:`adapter.py` + `plugin.yaml`) | +| `gateway/platforms/` | 共享的 `base.py` 与遗留/直接适配器(Signal、API server、webhooks 等) | ## 架构概览