af7dceaf77bbcd5dcafe4f65982c7cd7df5f4c4a
31 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
accd672054 |
fix(slack): MPIMs (group DMs) obey shared-surface mention gating + reaction guard
Group DMs (MPIMs) were classified as DMs and thereby exempted from every operator control that shared surfaces are supposed to honor: allowed_channels, require_mention, strict_mention, free_response_channels, and the reaction guard. Symptom: the bot added 👀/✅ to unmentioned MPIM messages and still invoked the agent (which then returned NO_REPLY) instead of the gateway dropping the event before model execution. Removing an MPIM from allowed_channels did not disable it. Root cause is the DM classification at adapter.py: is_dm = channel_type in {"im", "mpim"} used for BOTH routing exemptions and reaction gating. An MPIM is a shared surface (multiple humans can see and trigger the bot), not a private 1:1 DM, so it must be gated like a channel. This behavior was introduced/reinforced by a trail of Slack group-DM PRs: - #4633 fix(slack): treat group DMs (mpim) like DMs + reaction guard - #54632 fix(slack): subscribe to message.mpim + mpim scopes so group DMs work - #54663 fix(slack): group DMs work OOTB + reinstall nudge #54632/#54663 correctly made MPIM messages *reachable*; #4633 over-reached by giving them the DM mention/reaction *exemptions*. This corrects only that over-reach. Fix (minimal): introduce `is_one_to_one_dm = channel_type == "im"` and key the two EXEMPTION sites off it instead of `is_dm`: - mention/allowlist gating block (`if not is_one_to_one_dm and bot_uid:`) - reaction guard (`(is_one_to_one_dm or is_mentioned)`) `is_dm` is intentionally retained for session/thread scoping and chat_type labeling, where treating an MPIM as a persistent multi-party conversation is correct — only the mention/reaction exemptions were wrong. Docs: slack.md now distinguishes 1:1 DMs (mention-exempt) from group DMs (shared surface; obey require_mention/strict_mention/allowed_channels/ free_response_channels; reactions only when @mentioned). Tests: +7 in test_slack_mention.py (MPIM unmentioned dropped under require_mention and strict_mention; MPIM mentioned processed; MPIM off allowed_channels dropped; MPIM in free_response opted in; 1:1 IM still exempt; reaction guard drops unmentioned MPIM). Updated _would_process to model the is_one_to_one_dm gating + strict_mention. 72 passed. |
||
|
|
4b4349eb9a |
feat(cron/slack): flat in-channel continuable cron delivery surface
Add a per-platform `cron_continuable_surface` extra key (`thread` default | `in_channel`) so a continuable cron job can deliver FLAT into a Slack channel — no dedicated thread — and still be replied-to. In `in_channel` mode the scheduler skips the thread-open branch (leaves `thread_id=None`); the shipped origin-mirror then seeds the `(slack, chat_id, None)` shared-channel session — the same bucket `reply_in_thread: false` routes inbound channel replies to — so a plain channel reply continues the job in context. Design: specs/cron-inchannel-continuable (D1–D7, F5). Model B (shared-channel session), NOT anchoring to the delivery `ts` — on Slack replying to a specific message IS threading, so a `ts` anchor would only relocate the thread, never deliver true threadless continuable. - gateway/platforms/base.py: `supports_inchannel_continuable` capability flag (default False → unsupported platforms fail SAFE to `thread`). - plugins/platforms/slack/adapter.py: flag=True; `_cron_continuable_surface()` resolver (coerces to the two-value enum); `_warn_if_inchannel_without_flat_reply` connect-time warning (D5: warn, not hard-require — the misconfig fails safe). - gateway/config.py: shared-key bridge line (top-level OR nested config). - cron/scheduler.py: read the key generically from platform config, gate the `in_channel` branch on the adapter capability flag, skip thread-open. No new seed function (reuses the existing mirror — G6). Pairing (docs): `in_channel` + `reply_in_thread: false` + `require_mention: false` (or a free-response channel). Missing `reply_in_thread: false` fails safe to a threaded continuation. Gateway-side config flag — `/restart` to apply; NO Slack app reinstall. Tests (from inside the worktree, PYTHONPATH=$PWD): - +6 cron scheduler tests (in_channel skips thread-open; seeds flat channel session with thread_id=None; thread-mode regression; fail-safe on unsupported platform; value coercion). Prove-fail: removing the `and not in_channel_surface` guard turns the two load-bearing tests RED; restore → GREEN. - +10 slack resolver/capability/warning tests; +2 config-bridge tests. - tests/manual/cron_inchannel_e2e.py: offline E2E driving BOTH real legs (delivery seed + inbound reply keying) → both converge on (slack, C, None). - No regressions: test_slack.py 216 passed alone; broader sweep green (4 pre-existing cross-file-ordering failures reproduce identically on pristine origin/main). Docs: cron.md + slack.md + zh-Hans mirrors of both. |
||
|
|
7c7b489813 |
feat(slack): render markdown tables as native Block Kit table blocks
Replace the interim monospace table fallback with Slack's native `table` block (rows of rich_text cells). Addresses the core ask in #18918. - _table_block(): builds type:"table" with rich_text cells, so inline formatting (bold, links, code) renders inside cells. - Column alignment parsed from the markdown separator row (:---, :-:, --:) into column_settings (left = default/null-skip, center/right emitted). - Escaped pipes (\\|) are not treated as column separators. - Respects Slack's table limits (100 rows / 20 cols / 10k aggregate chars); oversized or unparseable tables gracefully fall back to aligned monospace (rich_text_preformatted), so a big table never breaks the message. Docs (EN + zh-Hans) updated to describe native tables + the fallback. Tests: native table shape, alignment->column_settings, inline-formatted cells, oversized/too-wide monospace fallback, escaped-pipe cell. Prove- failed against a stubbed _table_block (native-table tests fail, fallback tests stay green). All existing Slack tests still pass. |
||
|
|
b080b93ad8 |
feat(slack): opt-in Block Kit rendering for agent messages
Add platforms.slack.extra.rich_blocks (default off). When enabled, the final agent message is sent as Slack Block Kit blocks — section headers, dividers, and true nested lists via rich_text — instead of flat mrkdwn. - New plugins/platforms/slack/block_kit.py: pure markdown->blocks renderer (headers, dividers, nested ordered/bullet lists, blockquotes, fenced code; pipe-tables as aligned monospace since Block Kit has no robust table block). Enforces Slack's 50-block / 3000-char section limits and returns None to fall back to plain text on empty/oversized/unexpected input. Never raises. - adapter.send(): render blocks on the single-chunk primary message; a text= fallback is ALWAYS sent alongside (notifications/accessibility). - adapter.edit_message(): blocks only on finalize=True, so intermediate streaming edits stay plain mrkdwn (no per-flush block re-derivation). - Docs (EN + zh-Hans) + config example. Send-side only: no app reinstall. Tests: pure-renderer unit suite + adapter integration suite (blocks present when on, plain text when off, text fallback always set, finalize gating, multi-chunk fallback). Prove-failed against a stubbed renderer. |
||
|
|
34e616e778 |
feat(slack): nudge stale installs to add mpim scopes; mark message.mpim required
Follow-up to the group-DM manifest fix. The manifest change only helps NEW installs; existing apps keep their old (mpim-less) scopes until the admin reinstalls. Since a missing message.mpim event delivers nothing (no runtime API error to catch), detect stale installs at connect time from the auth.test x-oauth-scopes header and log an actionable reinstall nudge when im:history is granted but mpim:history is not. Also promote message.mpim from Recommended to Required in the docs event tables so the default setup path can't drop it. |
||
|
|
4125cc3b7c |
fix(slack): subscribe to message.mpim + mpim scopes so group DMs work
Group DMs (multi-person DMs, channel_type=mpim) were never delivered to
the Slack bot. The adapter already classifies mpim as a DM and replies
ambiently (adapter.py:2526, is_dm = channel_type in {im, mpim}), but the
generated app manifest only subscribed to message.im / im:history — the
1:1 DM pair. Without the message.mpim event subscription Slack drops
group-DM messages before the adapter ever sees them, so 1:1 DMs worked
while group-DM ambient mode was dead.
Add message.mpim to bot_events and mpim:history (the scope that event
requires per Slack docs) + mpim:read (mirrors im:read for the
conversations.info classification call) to bot_scopes. Update the
SLACK_BOT_TOKEN / SLACK_APP_TOKEN setup-help strings and the Slack docs
(EN + zh-Hans: scope table, event table, troubleshooting) so existing
installs are told to add the new scopes and reinstall.
Reported by an enterprise customer. Note: this is a manifest/scope
change, so it only takes effect after the app is reinstalled and the
new scopes are accepted.
Tests: assert message.mpim + mpim:history + mpim:read are in the
manifest (with and without assistant mode); both fail on current main
and pass with this change.
|
||
|
|
cd9a9cd8e5 |
fix(gateway): Slack approval UX in threads — block-size overflow + typed-prefix instruction text (#43444)
Two fixes for the reported Slack thread approval UX: 1. Slack Block Kit approval/confirm sends silently overflowed the 3000-char section-block cap (flat 2900-char truncation + header + reason), so long execute_code approvals failed with invalid_blocks and fell back to the plain-text prompt with no buttons. Budget the command preview against the rendered fixed parts so blocks never exceed the cap (send_exec_approval + send_slash_confirm). 2. The text fallbacks told users to reply /approve — which Slack blocks inside threads and Matrix clients reserve client-side. Add a typed_command_prefix capability flag on BasePlatformAdapter (default "/"; Slack and Matrix set "!" to match their existing bang-prefix rewrite) and use it in the shared fallback prompt builders (exec approval, update prompt, destructive slash confirm, expensive-model confirm) plus Matrix's reaction-prompt text. The slash-confirm text-intercept now also accepts bang-prefixed replies (!always, !cancel) since those keywords aren't registered commands and the adapters' rewrite doesn't touch them. |
||
|
|
eacce70a35 |
docs: comprehensive 2-week sweep of feature/PR coverage gaps (#28497)
Catch the website docs up to two weeks of merged work (May 4 – May 18, 2026, roughly 1,080 PRs). The audit found ~50 user-visible features that had landed in code with no docs footprint, plus a handful of stale pages. This PR closes every gap the scan turned up. New pages - user-guide/features/deliverable-mode.md — extension list, agent triggers, kanban_complete artifacts pattern, [[as_document]] override (PR #27813). - developer-guide/web-search-provider-plugin.md — authoring guide modeled on image-gen-provider-plugin, covering brave_free / ddgs / etc. (PR #25448). Providers / auth - Rename "Alibaba Cloud" → "Qwen Cloud (Alibaba DashScope)" everywhere the display label shows up; provider id stays `alibaba` (PR #24835). - Document OAuth refresh-token quarantine for xAI / MiniMax / Codex (PRs #28116 / #28118 / #28119). - Document Nous JWT minting from refresh token + invalid-refresh quarantine + cross-profile shared token store (PRs #27663 / #19712). - Add `## Microsoft Entra ID authentication (keyless)` section to azure-foundry guide — DefaultAzureCredential, RBAC, OpenAI + Anthropic routing details (PR #28101 / #9df9816da). - Custom providers `api_mode` is now prompted-and-persisted, not just URL autodetected (PR #25068). - Delegation honours `api_mode` + auto-detects anthropic_messages base URLs (PR #26824). - `x_search` auto-enables when xAI credentials are present (PR #27376). - Add `xAI Grok OAuth (SuperGrok)` row to providers headline table (PR #26534). - NVIDIA NIM billing-origin header is set automatically (PR #26585). Windows / installer - `install.ps1`: document `-Commit <sha>` and `-Tag <v>` pin params plus the BOM-strip / git-retry hardening (PR #28169). - Document Hermes Desktop thin installer + first-launch bootstrap (PR #27822). - Document `dep_ensure` Windows bootstrap (PR #27845). - Document install-method auto-detection (pip / git / homebrew / nixos) and the matching update command (PR #27843). Gateway / messaging - `/platform list|pause|resume` full description + circuit-breaker semantics (PR #26600). - Slack / Matrix / Mattermost get parallel `allowed_channels` / `allowed_rooms` allowlist sections matching Telegram/Discord/DingTalk (PR #21251). - Discord `allow_any_attachment` + `max_attachment_bytes` (config and env vars) (PR #27245). - Discord clarify-choice button rendering (PR #25485). - Telegram `guest_mode` @mention bypass for allowlisted groups (PR #22759). - Telegram `notifications` mode (`important` vs `all`) (PR #22793). - `[[as_document]]` skill / response directive for forcing document-style media delivery (PR #21210). CLI / TUI - `/new [name]` argument (PR #19637). - `/subgoal` user-supplied criteria appended to `/goal` (PR #25449). - `/exit --delete` flag confirmation prompts for destructive slash commands (PR #22687). - Status-bar additions: ▶ N background indicator (PR #27175), context compression count (PR #21218), YOLO mode banner+statusbar warning (PR #26238). - `display.timestamps` + `docker_extra_args` config keys (PR #23599). - TUI collapsible startup banner sections (PR #20625). - `HERMES_SESSION_ID` exported to tool subprocesses (PR #23847). i18n - Refresh display.language locale list from 8 → 16 (en, zh, zh-hant, ja, de, es, fr, tr, uk, af, ko, it, ga, pt, ru, hu) — matches `agent/i18n.py:SUPPORTED_LANGUAGES`. Tools / features - `vision_analyze` native-pixel passthrough for vision-capable callers, with auxiliary text-describer fallback (PR #22955). - `session_search` rewrite to the single-shape tool (discovery / scroll / browse modes) (PRs #27590 / #27840). - Clarify MCP transport scope: client supports stdio + SSE; embedded `hermes mcp serve` is stdio-only (PR #21227). - Web search backends table: add Brave Search (free tier) and DDGS rows (PR #21337). - ACP session-scoped edit auto-approval modes (PR #27862). - Curator rename map in the user-visible per-run summary (PR #22910). - Prompt caching feature page reference in features/overview.md — Claude cross-session 1-hour prefix cache on native Anthropic / OpenRouter / Nous Portal (PR #23828). - Cron per-job profile parameter (PR #28124). - `--no-skills` flag for `hermes profile create` (PR #20986). Build - Verified with `npm run build` in `website/`; both `en` and `zh-Hans` locales compile. Remaining broken-link/anchor warnings are pre-existing (`rl-training.md` from learning-path / overview; the zh-Hans translation lag the docs skill already calls out). |
||
|
|
6122a79aab |
feat(slack): support !cmd as alternate prefix for slash commands in threads (#25355)
Slack platform-blocks native slash commands inside thread replies ("/queue
is not supported in threads. Sorry!") and there is no app-side setting to
re-enable them. As a workaround, rewrite a leading '!' to '/' for any known
gateway command before downstream processing — so '!queue', '!stop',
'!model gpt-5.4' etc. work inside Slack threads (and anywhere else).
Only the first token is checked against is_gateway_known_command(), so
casual messages like '!nice work' pass through to the agent unchanged.
Downstream pipeline (MessageType.COMMAND tagging, gateway dispatcher,
thread reply routing) is unchanged.
Adds 6 tests covering rewrite, args preservation, thread routing,
casual-message passthrough, '@bot' suffix, and plain '/' still-works.
|
||
|
|
22ff6ca32b |
docs: two-week gap sweep — platforms, CLI, config, TUI, hooks, providers (#17727)
Covers ~60 merged PRs from Apr 15–29 that shipped user-visible behavior without docs coverage. No functional code changes; docs + static manifest regeneration only. Highlights: Stale / incorrect: - configuration.md: auxiliary auto-routing line was wrong since #11900; now correctly states auto routes to the main model, with a note on the cost trade-off and per-task override pattern. - integrations/providers.md + configuration.md compression intro: removed stale 'Gemini Flash via OpenRouter' claim. - website/static/api/model-catalog.json: rebuilt from hermes_cli/models.py so the live manifest picks up tencent/hy3-preview (and remains in sync for future model-catalog PRs). Platform messaging (#17417 #16997 #16193 #14315 #13151 #11794 #10610 #10283 #10246 #11564 #13178): - Signal: native formatting (bodyRanges), reply quotes, reactions. - Telegram: table rendering (bullets + code-block fallback), disable_link_previews, group_allowed_chats. - Slack: strict_mention config. - Discord: slash_commands disable, send_animation GIF, send_message native media attachments. - DingTalk: require_mention + allowed_users. CLI (#16052 #16539 #16566 #15841 #14798 #10043): - New 'hermes fallback' interactive manager. - New 'hermes update --check', '--backup' flag, and pre-update pairing snapshot behavior. - 'hermes gateway start/restart --all' multi-profile flag. - cron.md: 'hermes tools' as a platform, per-job enabled_toolsets, wakeAgent gate, context_from chaining. Config keys / env vars (#17305 #17026 #17000 #15077 #14557 #14227 #14166 #14730 #17008): - terminal.docker_run_as_host_user, display.runtime_metadata_footer, compression.hygiene_hard_message_limit, HINDSIGHT_TIMEOUT, skills.guard_agent_created, TAVILY_BASE_URL, security.allow_private_urls, agent.api_max_retries, gateway hot-reload of compression/context_length config edits. TUI / CLI UX (#17130 #17113 #17175 #17150 #16707 #12312 #12305 #12934 #14810 #14045 #17286 #17126): - HERMES_TUI_RESUME, HERMES_TUI_THEME, LaTeX rendering, busy-indicator styles, ctrl-x queued-message delete, git branch in status bar, per- prompt elapsed stopwatch, external-editor keybind, markdown stripping, TUI voice-mode parity, /agents overlay, /reload + /mouse. Gateway features (#16506 #15027 #13428 #12116): - Native multimodal image routing based on vision capability. - /usage account-limits section. - /steer slash command (added to reference + explanation in CLI). Plugins / hooks (#12929 #12972 #10763 #16364): - transform_tool_result, transform_terminal_output plugin hooks. - PluginContext.dispatch_tool() documented with slash-command example. - google_meet bundled plugin entry under built-in-plugins.md. Other (#16576 #16572 #16383 #15878 #15608 #15606 #14809 #14767 #14231 #14232 #14307 #13683 #12373 #11891 #11291 #10066): - hermes backup exclusions (WAL/SHM/journal + checkpoints/). - security.md hardline blocklist (floor below --yolo). - FHS install layout for root installs. - openssh-client + docker-cli baked into the Docker image. - MEDIA: tag supported extensions table (docs/office/archives/pdf). - Remote-to-host file sync on SSH/Modal/Daytona teardown. - 'hermes model' -> Configure Auxiliary Models interactive picker. - Podman support via HERMES_DOCKER_BINARY. Providers / STT / one-shot (#15045 #14473 #15704): - alibaba-coding-plan first-class provider entry. - xAI Grok STT as a 6th transcription option. - 'hermes -z' scripted one-shot mode + HERMES_INFERENCE_MODEL. Build: 'docusaurus build' succeeds. No new broken links/anchors; pre-existing warnings unchanged. |
||
|
|
8fb861ea6e |
feat(gateway/slack): support channel_skill_bindings
Extends the existing channel_skill_bindings mechanism (previously
Discord-only) to Slack, so a channel or DM can auto-load one or more
skills at session start without relying on the model's skill selector
for every short reply.
Motivation: Mats's German flashcards DM pushes a cron-driven card
5x/day; he responds with one-word guesses like 'work'. Previously each
reply required the main agent to decide whether to load german-flashcards
(full opus turn just to pick a skill). With the binding configured per
Slack channel, the skill is injected at session start and grading runs
directly.
Changes:
- Extract resolve_channel_skills() from DiscordAdapter._resolve_channel_skills
into gateway.platforms.base (now shared across adapters).
- DiscordAdapter._resolve_channel_skills delegates to the shared helper
(behavior preserved — existing test suite still passes unchanged).
- SlackAdapter: resolve channel_skill_bindings on each message and attach
auto_skill to MessageEvent. gateway/run.py already handles auto-skill
injection on new sessions; this just wires Slack through it.
- gateway/config.py: accept channel_skill_bindings in slack: block of
config.yaml (was Discord-only).
- Tests: new tests/gateway/test_slack_channel_skills.py with 11 cases
covering DM/thread/parent resolution, single-vs-list skills, dedup,
malformed entries. Discord suite unchanged.
- Docs: add 'Per-Channel Skill Bindings' section to Slack user guide.
Config example:
slack:
channel_skill_bindings:
- id: "D0ATH9TQ0G6"
skills: ["german-flashcards"]
|
||
|
|
778fd1898e |
fix(slack): surface attachment access diagnostics
Translate Slack attachment failures into actionable user-facing notices
instead of generic download errors. When a scope/auth/permission issue
breaks attachment processing, the user sees:
[Slack attachment notice]
- Slack attachment access failed for photo.jpg. Missing scope:
files:read. Update the Slack app scopes/settings and reinstall
the app to the workspace.
Two helpers do the translation:
_describe_slack_api_error — handles SlackApiError responses
(missing_scope, invalid_auth, file_not_found, access_denied, etc.)
_describe_slack_download_failure — handles httpx.HTTPStatusError
(401/403/404) and Slack-returns-HTML-sign-in fallbacks
Wired into three existing call sites:
- the Slack Connect files.info path (PR #11111) so scope errors
surface instead of being logged as generic "files.info failed"
- the image, audio, and document download paths so 401/403 and
HTML-body responses translate into actionable notices
Adjustment from original PR: dropped _probe_slack_file_access_issue,
the proactive pre-download files.info probe. It added one extra
Slack API call per attachment even on healthy ones, and overlapped
with the existing files.info call from PR #11111. The post-failure
translation path covers the same user-facing diagnostic value
without the per-message tax.
Also documents files:read scope more prominently in the Slack setup
guide and troubleshooting table.
Contributed back from https://github.com/xinbenlv/zn-hermes-agent.
Closes #7015.
Co-authored-by: xinbenlv <zzn+pa@zzn.im>
|
||
|
|
087e74d4d7 |
feat(slack): register every gateway command as a native slash (Discord/Telegram parity) (#16164)
Every command in COMMAND_REGISTRY (/btw, /stop, /model, /help, /new, /bg, /reset, ...) is now a first-class Slack slash command instead of a /hermes <subcommand>. Users get the same autocomplete-driven slash picker experience Slack users expect and that Discord and Telegram already provide. Previously Slack registered ONE native slash (/hermes) and split on the first word, so typing /btw in Slack's composer got 'couldn't find an app for /btw' because the workspace manifest never declared it. Changes - hermes_cli/commands.py: slack_native_slashes() + slack_app_manifest() generate a Slack manifest from the registry (canonical names + aliases + plugin commands), clamped to Slack's 50-slash cap with /hermes reserved as the catch-all. - gateway/platforms/slack.py: single regex matcher dispatches every registered slash to _handle_slash_command, which dispatches on command['command']. Legacy /hermes <subcommand> keeps working for backward compat with older workspace manifests. - hermes_cli/slack_cli.py + hermes_cli/main.py: new 'hermes slack manifest' command prints/writes a full manifest (display info, OAuth scopes, event subs, socket mode, slash commands) ready to paste into 'Create from manifest' or Features → App Manifest. - hermes_cli/setup.py: _setup_slack() now writes the manifest up-front and points users at the 'From an app manifest' flow; also offers to refresh the manifest on reconfigure for picking up new commands. - Tests: 14 new tests covering native-slash dispatch (/btw, /stop, /model), legacy /hermes <sub> compat, manifest structure, and telegram<->slack parity (every Telegram command must also register as a Slack slash). Existing /hermes-registration test updated to assert the new regex matches /hermes, /btw, /stop, /model, /help. - Docs: slack.md gains a 'Slash Commands' section + Option A manifest flow in Step 1; cli-commands.md documents 'hermes slack manifest'. Users pick up the new slashes by running 'hermes slack manifest --write' and pasting into Features → App Manifest → Edit in their Slack app config, then Save (Slack prompts for reinstall if scopes changed). |
||
|
|
54e0eb24c0 |
docs: correctness audit — fix wrong values, add missing coverage (#11972)
Comprehensive audit of every reference/messaging/feature doc page against the
live code registries (PROVIDER_REGISTRY, OPTIONAL_ENV_VARS, COMMAND_REGISTRY,
TOOLSETS, tool registry, on-disk skills). Every fix was verified against code
before writing.
### Wrong values fixed (users would paste-and-fail)
- reference/environment-variables.md:
- DASHSCOPE_BASE_URL default was `coding-intl.dashscope.aliyuncs.com/v1` \u2192
actual `dashscope-intl.aliyuncs.com/compatible-mode/v1`.
- MINIMAX_BASE_URL and MINIMAX_CN_BASE_URL defaults were `/v1` \u2192 actual
`/anthropic` (Hermes calls MiniMax via its Anthropic Messages endpoint).
- reference/toolsets-reference.md MCP example used the non-existent nested
`mcp: servers:` key \u2192 real key is the flat `mcp_servers:`.
- reference/skills-catalog.md listed ~20 bundled skills that no longer exist
on disk (all moved to `optional-skills/`). Regenerated the whole bundled
section from `skills/**/SKILL.md` \u2014 79 skills, accurate paths and names.
- messaging/slack.md ":::info" callout claimed Slack has no
`free_response_channels` equivalent; both the env var and the yaml key are
in fact read.
- messaging/qqbot.md documented `QQ_MARKDOWN_SUPPORT` as an env var, but the
adapter only reads `extra.markdown_support` from config.yaml. Removed the
env var row and noted config-only nature.
- messaging/qqbot.md `hermes setup gateway` \u2192 `hermes gateway setup`.
### Missing coverage added
- Providers: AWS Bedrock and Qwen Portal (qwen-oauth) \u2014 both in
PROVIDER_REGISTRY but undocumented everywhere. Added sections to
integrations/providers.md, rows to quickstart.md and fallback-providers.md.
- integrations/providers.md "Fallback Model" provider list now includes
gemini, google-gemini-cli, qwen-oauth, xai, nvidia, ollama-cloud, bedrock.
- reference/cli-commands.md `--provider` enum and HERMES_INFERENCE_PROVIDER
enum in env-vars now include the same set.
- reference/slash-commands.md: added `/agents` (alias `/tasks`) and `/copy`.
Removed duplicate rows for `/snapshot`, `/fast` (\u00d72), `/debug`.
- reference/tools-reference.md: fixed "47 built-in tools" \u2192 52. Added
`feishu_doc` and `feishu_drive` toolset sections.
- reference/toolsets-reference.md: added `feishu_doc` / `feishu_drive` core
rows + all missing `hermes-<platform>` toolsets in the platform table
(bluebubbles, dingtalk, feishu, qqbot, wecom, wecom-callback, weixin,
homeassistant, webhook, gateway). Fixed the `debugging` composite to
describe the actual `includes=[...]` mechanism.
- reference/optional-skills-catalog.md: added `fitness-nutrition`.
- reference/environment-variables.md: added NOUS_BASE_URL,
NOUS_INFERENCE_BASE_URL, NVIDIA_API_KEY/BASE_URL, OLLAMA_API_KEY/BASE_URL,
XAI_API_KEY/BASE_URL, MISTRAL_API_KEY, AWS_REGION/AWS_PROFILE,
BEDROCK_BASE_URL, HERMES_QWEN_BASE_URL, DISCORD_ALLOWED_CHANNELS,
DISCORD_PROXY, TELEGRAM_REPLY_TO_MODE, MATRIX_DEVICE_ID, MATRIX_REACTIONS,
QQBOT_HOME_CHANNEL_NAME, QQ_SANDBOX.
- messaging/discord.md: documented DISCORD_ALLOWED_CHANNELS, DISCORD_PROXY,
HERMES_DISCORD_TEXT_BATCH_DELAY_SECONDS and HERMES_DISCORD_TEXT_BATCH_SPLIT
_DELAY_SECONDS (all actively read by the adapter).
- messaging/matrix.md: documented MATRIX_REACTIONS (default true).
- messaging/telegram.md: removed the redundant second Webhook Mode section
that invented a `telegram.webhook_mode: true` yaml key the adapter does
not read.
- user-guide/features/hooks.md: added `on_session_finalize` and
`on_session_reset` (both emitted via invoke_hook but undocumented).
- user-guide/features/api-server.md: documented GET /health/detailed, the
`/api/jobs/*` CRUD surface, POST /v1/runs, and GET /v1/runs/{id}/events
(10 routes that were live but undocumented).
- user-guide/features/fallback-providers.md: added `approval` and
`title_generation` auxiliary-task rows; added gemini, bedrock, qwen-oauth
to the supported-providers table.
- user-guide/features/tts.md: "seven providers" \u2192 "eight" (post-xAI add
oversight in #11942).
- user-guide/configuration.md: TTS provider enum gains `xai` and `gemini`;
yaml example block gains `mistral:`, `gemini:`, `xai:` subsections.
Auxiliary-provider enum now enumerates all real registry entries.
- reference/faq.md: stale AIAgent/config examples bumped from
`nous/hermes-3-llama-3.1-70b` and `claude-sonnet-4.6` to
`claude-opus-4.7`.
### Docs-site integrity
- guides/build-a-hermes-plugin.md referenced two nonexistent hooks
(`pre_api_request`, `post_api_request`). Replaced with the real
`on_session_finalize` / `on_session_reset` entries.
- messaging/open-webui.md and features/api-server.md had pre-existing
broken links to `/docs/user-guide/features/profiles` (actual path is
`/docs/user-guide/profiles`). Fixed.
- reference/skills-catalog.md had one `<1%` literal that MDX parsed as a
JSX tag. Escaped to `<1%`.
### False positives filtered out (not changed, verified correct)
- `/set-home` is a registered alias of `/sethome` \u2014 docs were fine.
- `hermes setup gateway` is valid syntax (`hermes setup \<section\>`);
changed in qqbot.md for cross-doc consistency, not as a bug fix.
- Telegram reactions "disabled by default" matches code (default `"false"`).
- Matrix encryption "opt-in" matches code (empty env default \u2192 disabled).
- `pre_api_request` / `post_api_request` hooks do NOT exist in current code;
documented instead the real `on_session_finalize` / `on_session_reset`.
- SIGNAL_IGNORE_STORIES is already in env-vars.md (subagent missed it).
Validation:
- `docusaurus build` \u2014 passes (only pre-existing nix-setup anchor warning).
- `ascii-guard lint docs` \u2014 124 files, 0 errors.
- 22 files changed, +317 / \u2212158.
|
||
|
|
0d05bd34f8 |
feat: extend channel_prompts to Telegram, Slack, and Mattermost
Extract resolve_channel_prompt() shared helper into gateway/platforms/base.py. Refactor Discord to use it. Wire channel_prompts into Telegram (groups + forum topics), Slack (channels), and Mattermost (channels). Config bridging now applies to all platforms (not just Discord). Added channel_prompts defaults to telegram/slack/mattermost config sections. Docs added to all four platform pages with platform-specific examples (topic inheritance for Telegram, channel IDs for Slack, etc.). |
||
|
|
448b8bfb7c | docs: add slack files:read scope | ||
|
|
afe6c63c52 |
docs: comprehensive docs audit — cover 13 features from last week's PRs (#5815)
Cover documentation gaps found by auditing all 50+ merged PRs from the past week:
tools-reference.md:
- Fix stale tool count (47→46, 11→10 browser tools) after browser_close removal
- Document notify_on_complete parameter in terminal tool description
telegram.md:
- Add Interactive Model Picker section (inline keyboard, provider/model drill-down)
discord.md:
- Add Interactive Model Picker section (Select dropdowns, 120s timeout)
- Add Native Slash Commands for Skills section (auto-registration at startup)
signal.md:
- Expand Attachments section with outgoing media delivery (send_image_file,
send_voice, send_video, send_document via MEDIA: tags)
webhooks.md:
- Document {__raw__} special template token for full payload access
- Document Forum Topic Delivery via message_thread_id in deliver_extra
slack.md:
- Fix stale/misleading thread reply docs — thread replies no longer require
@mention when bot has active session (3 locations updated)
security.md:
- Add cross-session isolation (layer 6) and input sanitization (layer 7)
to security layers overview
feishu.md:
- Add WebSocket Tuning section (ws_reconnect_interval, ws_ping_interval)
- Add Per-Group Access Control section (group_rules with 5 policy types)
credential-pools.md:
- Add Delegation & Subagent Sharing section
delegation.md:
- Update key properties to mention credential pool inheritance
providers.md:
- Add Z.AI Endpoint Auto-Detection note
- Add xAI (Grok) Prompt Caching section
skills-catalog.md:
- Add p5js to creative skills category
|
||
|
|
c58e16757a |
docs: fix 40+ discrepancies between documentation and codebase (#5818)
Comprehensive audit of all ~100 doc pages against the actual code, fixing: Reference docs: - HERMES_API_TIMEOUT default 900 -> 1800 (env-vars) - TERMINAL_DOCKER_IMAGE default python:3.11 -> nikolaik/python-nodejs (env-vars) - compression.summary_model default shown as gemini -> actually empty string (env-vars) - Add missing GOOGLE_API_KEY, GEMINI_API_KEY, GEMINI_BASE_URL env vars (env-vars) - Add missing /branch (/fork) slash command (slash-commands) - Fix hermes-cli tool count 39 -> 38 (toolsets-reference) - Fix hermes-api-server drop list to include text_to_speech (toolsets-reference) - Fix total tool count 47 -> 48, standalone 14 -> 15 (tools-reference) User guide: - web_extract.timeout default 30 -> 360 (configuration) - Remove display.theme_mode (not implemented in code) (configuration) - Remove display.background_process_notifications (not in defaults) (configuration) - Browser inactivity timeout 300/5min -> 120/2min (browser) - Screenshot path browser_screenshots -> cache/screenshots (browser) - batch_runner default model claude-sonnet-4-20250514 -> claude-sonnet-4.6 - Add minimax to TTS provider list (voice-mode) - Remove credential_pool_strategies from auth.json example (credential-pools) - Fix Slack token path platforms/slack/ -> root ~/.hermes/ (slack) - Fix Matrix store path for new installs (matrix) - Fix WhatsApp session path for new installs (whatsapp) - Fix HomeAssistant config from gateway.json to config.yaml (homeassistant) - Fix WeCom gateway start command (wecom) Developer guide: - Fix tool/toolset counts in architecture overview - Update line counts: main.py ~5500, setup.py ~3100, run.py ~7500, mcp_tool ~2200 - Replace nonexistent agent/memory_store.py with memory_manager.py + memory_provider.py - Update _discover_tools() list: remove honcho_tools, add skill_manager_tool - Add session_search and delegate_task to intercepted tools list (agent-loop) - Fix budget warning: two-tier system (70% caution, 90% warning) (agent-loop) - Fix gateway auth order (per-platform first, global last) (gateway-internals) - Fix email_adapter.py -> email.py, add webhook.py + api_server.py (gateway-internals) - Add 7 missing providers to provider-runtime list Other: - Add Docker --cap-add entries to security doc - Fix Python version 3.10+ -> 3.11+ (contributing) - Fix AGENTS.md discovery claim (not hierarchical walk) (tips) - Fix cron 'add' -> canonical 'create' (cron-internals) - Add pre_api_request/post_api_request hooks to plugin guide - Add Google/Gemini provider to providers page - Clarify OPENAI_BASE_URL deprecation (providers) |
||
|
|
798a7b99e4 |
docs: add Configuration Options section to Slack docs (#4644)
* docs: add Configuration Options section to Slack docs Documents all config.yaml options for the Slack bot: - Thread & reply behavior (reply_to_mode, reply_broadcast) - Session isolation (group_sessions_per_user) - Mention & trigger behavior (require_mention, mention_patterns, reply_prefix) - Unauthorized user handling (unauthorized_dm_behavior) - Voice transcription (stt_enabled) - Full example config showing all options together Includes a note about Slack's hardcoded @mention requirement in channels (no free_response_channels equivalent like Discord/Telegram). * docs: consolidate reply_in_thread into Configuration Options section Folds the standalone Reply Threading subsection from PR #4643 into the Thread & Reply Behavior subsection, keeping all config options in one place. Adds reply_in_thread to the table and full example. |
||
|
|
241cbeeccd | docs: add reply_in_thread config to Slack docs | ||
|
|
7e0c2c3ce3 |
docs: comprehensive documentation audit — fix 9 HIGH, 20+ MEDIUM gaps (#4087)
Reference docs fixes: - cli-commands.md: remove non-existent --provider alibaba, add hermes profile/completion/plugins/mcp to top-level table, add --profile/-p global flag, add --source chat option - slash-commands.md: add /yolo and /commands, fix /q alias conflict (resolves to /queue not /quit), add missing aliases (/bg, /set-home, /reload_mcp, /gateway) - toolsets-reference.md: fix hermes-api-server (not same as hermes-cli, omits clarify/send_message/text_to_speech) - profile-commands.md: fix show name required not optional, --clone-from not --from, add --remove/--name to alias, fix alias path, fix export/ import arg types, remove non-existent fish completion - tools-reference.md: add EXA_API_KEY to web tools requires_env - mcp-config-reference.md: add auth key for OAuth, tool name sanitization - environment-variables.md: add EXA_API_KEY, update provider values - plugins.md: remove non-existent ctx.register_command(), add ctx.inject_message() Feature docs additions: - security.md: add /yolo mode, approval modes (manual/smart/off), configurable timeout, expanded dangerous patterns table - cron.md: add wrap_response config, [SILENT] suppression - mcp.md: add dynamic tool discovery, MCP sampling support - cli.md: add Ctrl+Z suspend, busy_input_mode, tool_preview_length - docker.md: add skills/credential file mounting Messaging platform docs: - telegram.md: add webhook mode, DoH fallback IPs - slack.md: add multi-workspace OAuth support - discord.md: add DISCORD_IGNORE_NO_MENTION - matrix.md: add MSC3245 native voice messages - feishu.md: expand from 129 to 365 lines (encrypt key, verification token, group policy, card actions, media, rate limiting, markdown, troubleshooting) - wecom.md: expand from 86 to 264 lines (per-group allowlists, media, AES decryption, stream replies, reconnection, troubleshooting) Configuration docs: - quickstart.md: add DeepSeek, Copilot, Copilot ACP providers - configuration.md: add DeepSeek provider, Exa web backend, terminal env_passthrough/images, browser.command_timeout, compression params, discord config, security/tirith config, timezone, auxiliary models 21 files changed, ~1000 lines added |
||
|
|
5cdc24c2e2 |
docs(slack): add missing Messages Tab setup step (#3590)
Without enabling the Messages Tab in App Home settings, users see "Sending messages to this app has been turned off" when trying to DM the bot — even with all correct scopes and event subscriptions. Add Step 5 (Enable the Messages Tab) between Event Subscriptions and Install App, with a danger admonition. Also add troubleshooting entry for this specific error message. Renumber subsequent steps (6→7→8→9). Co-authored-by: Alberto Leal <mail4alberto@gmail.com> |
||
|
|
e2c81c6e2f |
docs: add missing skills, CLI commands, and messaging env vars
Complete the documentation gaps identified in the previous audit: Skills catalogs: - skills-catalog.md: Add 7 missing bundled skills — data-science/ jupyter-live-kernel, dogfood/hermes-agent-setup, inference-sh/ inference-sh-cli, mlops/huggingface-hub, productivity/linear, research/parallel-cli, social-media/xitter - optional-skills-catalog.md: Add 8 missing optional skills — blockchain/base, creative/blender-mcp, creative/meme-generation, mcp/fastmcp, productivity/telephony, research/bioinformatics, security/oss-forensics, security/sherlock CLI commands reference: - cli-commands.md: Add full documentation for hermes mcp (add/remove/ list/test/configure) and hermes plugins (install/update/remove/list) Messaging platform docs: - discord.md: Add DISCORD_REQUIRE_MENTION and DISCORD_FREE_RESPONSE_CHANNELS to manual config env vars section - signal.md: Add SIGNAL_ALLOW_ALL_USERS to env var reference table - slack.md: Add SLACK_HOME_CHANNEL_NAME to config section |
||
|
|
678e0bd9cc | docs: clarify Slack thread reply behavior | ||
|
|
95939a1b51 | docs: clarify gateway service scopes (#1378) | ||
|
|
e099117a3b | docs: complete voice mode docs | ||
|
|
984f00e0b0 |
docs: expand Docusaurus coverage across CLI, tools, skills, and skins (#1232)
- add code-derived reference pages for slash commands, tools, toolsets, bundled skills, and official optional skills - document the skin system and link visual theming separately from conversational personality - refresh quickstart, configuration, environment variable, and messaging docs to match current provider, gateway, and browser behavior - fix stale command, session, and Home Assistant configuration guidance |
||
|
|
74c214e957 |
feat(honcho): async memory integration with prefetch pipeline and recallMode
Adds full Honcho memory integration to Hermes: - Session manager with async background writes, memory modes (honcho/hybrid/local), and dialectic prefetch for first-turn context warming - Agent integration: prefetch pipeline, tool surface gated by recallMode, system prompt context injection, SIGTERM/SIGINT flush handlers - CLI commands: setup, status, mode, tokens, peer, identity, migrate - recallMode setting (auto | context | tools) for A/B testing retrieval strategies - Session strategies: per-session, per-repo (git tree root), per-directory, global - Polymorphic memoryMode config: string shorthand or per-peer object overrides - 97 tests covering async writes, client config, session resolution, and memory modes |
||
|
|
ac58309dbd |
docs: improve Slack setup guide with channel event subscriptions and scopes
The #1 support issue with Slack is 'bot works in DMs but not channels'. This is almost always caused by missing event subscriptions (message.channels, message.groups) or missing OAuth scopes (channels:history, groups:history). Changes: - slack.md: Move channels:history and groups:history from optional to required scopes. Move message.channels and message.groups to required events. Add new 'How the Bot Responds' section explaining DM vs channel behavior. Add Step 8 for inviting bot to channels. Expand troubleshooting table with specific 'works in DMs not channels' entry. Add quick checklist for channel debugging. - setup.py: Expand Slack setup wizard with all required scopes, event subscriptions, and a warning that without message.channels/message.groups the bot only works in DMs. Add link to full docs. Improve Member ID discovery instructions. - config.py: Update SLACK_BOT_TOKEN and SLACK_APP_TOKEN descriptions to list required scopes and event subscriptions inline. |
||
|
|
a9c35f9175 |
docs: comprehensive rewrite of all messaging platform setup guides
All four platform guides rewritten from thin ~60-line summaries to comprehensive step-by-step setup guides with current (2025-2026) info: telegram.md (74 → 196 lines): - Full BotFather walkthrough with customization commands - Privacy mode section with critical group chat gotcha - Multiple user ID discovery methods - Voice message setup (Whisper STT + TTS bubbles + ffmpeg) - Group chat usage patterns and admin mode - Recent Bot API features (privacy policy requirement, streaming) - Troubleshooting table (6 issues) discord.md (57 → 260 lines): - Complete Developer Portal walkthrough (application, bot, intents) - Detailed Privileged Gateway Intents section with warning about Message Content Intent being #1 failure cause - Invite URL generation via Installation tab (new 2024) and manual - Permission integer calculation (274878286912 recommended) - Developer Mode user ID discovery - Bot behavior documentation (DMs, channels, no-prefix) - Troubleshooting table (6 issues) slack.md (57 → 214 lines): - Warning about classic Slack apps deprecated since March 2025 - Full scope tables (required + optional) with purposes - Socket Mode setup with App-Level Token (xapp-) - Event Subscriptions configuration - User ID discovery via profile - Two-token architecture explained (xoxb- + xapp-) - Troubleshooting table whatsapp.md (77 → 193 lines): - Clarified whatsapp-web.js (not Business API) with ban risk warnings - Linux Chromium dependencies (Debian + Fedora) - Setup wizard QR code scanning workflow - Session persistence with LocalAuth - Second phone number options with cost table - WhatsApp Web protocol update warnings - Troubleshooting table (7 issues) Docusaurus build verified clean. |
||
|
|
ada3713e77 |
feat: add documentation website (Docusaurus)
- 25 documentation pages covering Getting Started, User Guide, Developer Guide, and Reference - Docusaurus with custom amber/gold theme matching the landing page branding - GitHub Actions workflow to deploy landing page + docs to GitHub Pages - Landing page at root, docs at /docs/ on hermes-agent.nousresearch.com - Content extracted and restructured from existing repo docs (README, AGENTS.md, CONTRIBUTING.md, docs/) - Auto-deploy on push to main when website/ or landingpage/ changes |