Skip to content

feat(desktop): bundle Bot Mode as built-in default-on plugin + core teammate protocol - #87886

Merged
teknium1 merged 10 commits into
mainfrom
feat/bundle-bot-mode-desktop
Aug 17, 2026
Merged

feat(desktop): bundle Bot Mode as built-in default-on plugin + core teammate protocol#87886
teknium1 merged 10 commits into
mainfrom
feat/bundle-bot-mode-desktop

Conversation

@teknium1

@teknium1 teknium1 commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Summary

Bot Mode is now part of the desktop app: the Hermes-Bot-Mode plugin ships bundled and ON by default, and the bot-to-bot messaging protocol moves out of user SOUL.md files into a core stable-tier system-prompt section that covers every session of every profile — including the headless hermes -p <bot> chat sessions teammates start.

Changes

  • apps/desktop/src/plugins/hermes-bots/ — adopted from NousResearch/Hermes-Bot-Mode @ c19baba + the multi-source roster (Hermes-Bot-Mode#68): the Bots panel merges the active gateway's profiles.list with the host.agents() union roster from feat(desktop): multi-source agents end-to-end — sockets, roster, SDK, fan-out updates #86875, showing bots from every registered Desktop connection (feature-detected; single-source behavior unchanged on older builds). Unchanged plugin.js form otherwise, description added for the Settings inventory; default-on, live-disable via Settings → Plugins
  • apps/desktop/src/contrib/plugins.ts — bundled glob accepts plugin.js
  • apps/desktop/src/contrib/runtime-loader.ts — disk/runtime copy of a bundled plugin id is skipped (pre-adoption standalone installs can't double-register)
  • apps/desktop/package.jsoncheck:test:plugins runs the plugin suite in js-tests CI
  • tools/bot_mode_probe.py (+ system_prompt/agent_init/config_defaults wiring) — agent.bot_mode_protocol (default on): silent unless a profile carries ui_meta['hermes-bots']; silent when SOUL.md has the legacy section; cached per (process, home), keyed off the agent's own home; byte-stable across rebuilds
  • tui_gateway/methods_profiles.pyprofiles.list gains a bot_mode_protocol capability flag; the bundled plugin gates all SOUL protocol writes on it (backfill, composeSoul, Edit save). Older gateways keep the plugin-side SOUL-append fallback
  • website/docs/user-guide/desktop.md — Bot Mode section

Validation

Check Result
Plugin suite (node --test) 143/143
tests/tools/test_bot_mode_probe.py 6/6
tests/agent/test_system_prompt.py + env_probe 39/39
desktop check:lint (tsc ×3 + eslint) 0 errors
contrib plugin/runtime-loader vitest 10/10
E2E real build_system_prompt section present on managed home, byte-stable, flag-off absent, silent on plain installs (+916B only when managed)

Supersedes the SOUL-backfill half of Hermes-Bot-Mode#99 — credit @kaduxo, whose handle fix, hermes profile list correction, and idempotent-append guards ship in the bundled plugin.

Infographic

Bot Mode built in

@teknium1
teknium1 requested a review from a team August 16, 2026 18:18
@github-actions

github-actions Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

૮ >ﻌ< ა ci review

ran on 9687e5a — feat: sync bundled Bot Mode with multi-source roster (Hermes

⚠️ Warnings

OSV vulnerability scan · View job

5 known vulnerabilities found in pinned dependencies.

How to fix:

Review the findings in the Security tab. Update the affected dependencies if a patched version is available.


debug info

CI timings

CI timings · View report · View job

Wall time 3m19s vs 3m21s (-1.0%). 16 job(s) slower, 17 faster, 5 unchanged.

  • Docs Site / docs-site-checks: +24.0s
  • Python tests / Run tests slice 3/12: +20.0s
  • Python tests / Run tests slice 12/12: +16.0s
  • Python tests / Run tests slice 6/12: +12.0s
  • OS-specific tests / Windows-only tests: -12.0s

@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/desktop Electron desktop app (apps/desktop/*) comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/tui Terminal UI (ui-tui/ + tui_gateway/) area/config Config system, migrations, profiles needs-decision Awaiting maintainer decision before any implementation labels Aug 16, 2026
…n plugin

Adopts the Hermes-Bot-Mode desktop plugin (NousResearch/Hermes-Bot-Mode)
into apps/desktop/src/plugins/hermes-bots/, registered by the bundled
vite glob and ON by default. It stays a pure @hermes/plugin-sdk consumer
in plain-ESM plugin.js form; users disable it live in Settings > Plugins.

- contrib/plugins.ts: bundled glob accepts plugin.js entries
- contrib/runtime-loader.ts: a disk/runtime copy of an id that ships
  bundled is skipped (standalone installs predating adoption cannot
  double-register)
- package.json: check:test:plugins runs the plugin's node:test suite in
  CI (138 tests)
- source: Hermes-Bot-Mode @ c19baba, incl. today's #107/#103/#99 merges
…tion

Replaces the plugin-side SOUL.md protocol append: on Bot-Mode-managed
installs (any profile carrying ui_meta['hermes-bots']) the prompt builder
injects the "Messaging other agents" section into every session of every
profile — including headless `hermes -p <bot> chat` sessions a teammate
starts — so bot handoffs work without mutating user-authored SOUL files.

- tools/bot_mode_probe.py: silent-when-unmanaged probe, cached per
  (process, home), keyed off the agent's OWN home (not ambient
  HERMES_HOME); silent when SOUL.md already carries the legacy section
- agent/system_prompt.py + agent_init.py + config_defaults.py: wired as
  agent.bot_mode_protocol (default True), stable tier, byte-stable
  across rebuilds (E2E-verified against the real build_system_prompt)
- tui_gateway profiles.list gains bot_mode_protocol capability flag;
  the bundled plugin gates ALL SOUL protocol writes on it (backfill,
  composeSoul, Edit save) — older gateways keep the SOUL-append path
- overhead: ~916 bytes, only on Bot-Mode installs; zero elsewhere

Supersedes the SOUL backfill half of Hermes-Bot-Mode#99 (credit
@kaduxo — the handle fix, `hermes profile list` correction, and
idempotent-append guards from that PR ship in the bundled plugin).
apps/desktop/src/**/*.js is gitignored (stale tsc output shadows .tsx),
which silently dropped the hermes-bots plugin.js from the adoption
commit — tests shipped, source didn't, CI ENOENT'd. Negate the pattern
for src/plugins/*/plugin.js: adopted plain-ESM plugins have no .tsx
sibling, so the shadow hazard cannot apply.
… sessions

Per review: the protocol belongs only in official Bot Mode interactions,
not every session on a managed install. The prompt builder now injects
the section only when the agent's session row is titled "Bot Chat"
(BOT_CHAT_TITLE, matching the desktop's createCanonicalChat pin and the
`hermes -p <bot> chat -c "Bot Chat"` resume target). Regular sessions
never carry it; the desktop composer middleware owns @mention sends.

Title is read once at first prompt build and the rendered prompt is
cached + DB-restored — cache-safe. E2E against the real AIAgent +
SessionDB: absent in an untitled session, present in Bot Chat,
byte-stable across rebuilds, absent after retitle, absent with the
flag off. Overhead unchanged (~916B, Bot Chat sessions only).
Found in live desktop E2E: the generated-identity path of composeSoul
still appended the protocol section even when the backend injects it
into the system prompt. New agents now get a clean identity-only SOUL
against capable backends; older gateways keep the append. Covered in
the capability-suppression test.
Live desktop E2E caught a write-ordering bug the automated E2E missed:
tui_gateway applies pending_title to state.db AFTER the first turn, but
the system prompt builds at turn START — the DB-title gate saw nothing
and the Bot Chat was cached protocol-less forever. The gateway now
hands the agent its intended title at construction and the gate checks
the hint first, DB second (CLI/messaging-gateway paths unchanged).

Live-verified on the running desktop: fresh bot's Bot Chat persisted
with the protocol section, handle, and roster in its system prompt;
regular sessions and SOUL.md untouched.
…at sessions

Bot Chats break the "new sessions come often" assumption behind
build-once system prompts: capability edits used to sit invisible until
/new or compression, and the frozen birth date became misinformation.

- tools/bot_mode_probe.py: capability_fingerprint() hashes the profile's
  capability surface (disabled skills, toolset pins, MCP config, SOUL.md,
  installed skills, Bot-Mode roster); Bot Chat prompts embed the 12-hex
  epoch stamp
- agent/conversation_loop.py restore path: stored Bot Chat prompt whose
  epoch mismatches disk → ONE rebuild (through a cleared skills-prompt
  cache so new installs appear), persisted so the next turn reuses the
  new bytes verbatim. Prompts without a stamp — every non-Bot-Chat
  session — never take the branch; probe failure fails closed to reuse
- agent/system_prompt.py: Bot Chat prompts are timeless — the
  "Conversation started:" date is dropped (timezone kept); no ticking
  fields in an eternal session
- tui_gateway: _sync_bot_capabilities at turn start rebuilds the live
  agent (tool definitions are construction-baked) when the fingerprint
  moves, same session id/history, with a user-visible notice

Cache stance: this is the /model exception applied to capabilities — a
loud, user-initiated, once-per-change prefix break. Unchanged state
hashes identically and stored bytes are reused verbatim (E2E-proven).

Validation: 9 probe unit tests incl. per-axis fingerprint changes;
E2E v3 against the real restore path (fresh build → verbatim reuse →
skill install → single refresh w/ new skill in index → verbatim reuse;
regular sessions dated, unstamped, never refreshed); tests/agent/
4647/4647.
Bot Chats created before the epoch mechanism persisted prompts with no
protocol section and no stamp — the staleness check only fires on
stamped prompts, so pre-existing bots would never learn to message
teammates. stored_bot_chat_prompt_needs_upgrade() migrates them: one
rebuild, title-gated to Bot Chat, only when the probe would actually
emit a section (SOUL-append legacies and unmanaged installs are left
alone — rebuilding those would loop). The rebuilt prompt carries the
stamp, so the upgrade can never re-fire.

E2E v3b through the real restore path: legacy Bot Chat upgraded once
then verbatim-reused; legacy regular sessions byte-untouched.
tests/agent/ 4648/4648.
The config-read guard (test_config_read_guard) correctly flagged the
probe's raw yaml.safe_load of config.yaml — raw reads miss the managed
overlay, env expansion, and normalization. Use load_config_readonly()
under a scoped HERMES_HOME override instead. E2E v3/v3b and the guard
both green.
…#68)

Pulls the multi-source roster into the bundled plugin: profiles.list rows
from the active gateway are merged with the host.agents() union roster
(hermes-agent #86875), so the Bots panel shows agents from every registered
Desktop connection with @name-device handles for duplicates. Feature-detected
and best-effort — an older Desktop build or roster failure leaves the
single-source list untouched.

Adapted for the bundle:
- useRoster queryFn combines the bot_mode_protocol capability read (which
  landed after #68 was cut) with the multi-source merge
- multi-source-roster tests updated for the namespace SDK import harness
- soul-protocol-backfill anchor widened for the new botHandle(name, bot)
  signature

Plugin suite: 143/143.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/config Config system, migrations, profiles comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/desktop Electron desktop app (apps/desktop/*) comp/tui Terminal UI (ui-tui/ + tui_gateway/) needs-decision Awaiting maintainer decision before any implementation P3 Low — cosmetic, nice to have type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants