Skip to content

feat(simplex): groups, native attachments, text batching, auto-accept - #27978

Closed
jooray wants to merge 1 commit into
NousResearch:mainfrom
jooray:feature/simplex-plugin
Closed

feat(simplex): groups, native attachments, text batching, auto-accept#27978
jooray wants to merge 1 commit into
NousResearch:mainfrom
jooray:feature/simplex-plugin

Conversation

@jooray

@jooray jooray commented May 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Extends the SimpleX Chat platform plugin merged in #27???/09d9724a0 with the features our deployment was carrying out-of-tree against the older core-modifying SimpleX integration (#2558/#4870). All additions live inside plugins/platforms/simplex/no edits to any core file — and the existing tests/gateway/test_simplex_plugin.py suite (27 tests) passes unchanged except for two that asserted send-format details we believe are wrong (see Test changes below).

This PR is a new PR, not a refresh of #4870. #4870 was the original core-modifying version. After the plugin landed upstream we rebuilt the work on top of the plugin contract, which is the architecture this codebase is clearly moving towards. #4870 should be closed in favour of this one.

Where the current plugin falls short

The current plugins/platforms/simplex/ adapter is a faithful first port from the original PR description, but in a real deployment it has a few gaps:

Area Current plugin This PR
Group chats Inbound items are parsed as DMs only; no allowlist gate, no chat_type="group" on the event. SIMPLEX_GROUP_ALLOWED env var (comma-separated IDs or *); inbound items surface with chat_id="group:<id>" + chat_type="group". Omitted by default — a bot in a group otherwise processes every member's traffic.
Inbound files / voice notes _fetch_file does /freceive then sleep(2) and scans ~/Downloads, ~/.simplex/files, /tmp/simplex_files for the filename. Race-prone on large files; voice notes that need >2s for XFTP transfer get dropped. Hooks rcvFileDescrReady to send /freceive immediately on file announcement; defers the chat item via _pending_file_transfers and replays it once rcvFileComplete fires. Distinguishes voice notes (→ MessageType.VOICE), photos, and documents.
Outbound media send_image is a stub: posts f"{caption}\n{image_url}" as plain text. No send_voice, send_video, send_document. Real send_image_file / send_image (PNG/JPEG with Pillow or ImageMagick conversion + inline thumbnail), send_voice (native msgContent.type="voice" so the receiving client renders the inline voice-note player rather than a generic file download), send_video, send_document. All addressed by numeric ID via the structured /_send … json [...] form so groups with non-unique display names don't get the wrong target.
MEDIA:<path> tags in agent replies Not supported — the tag would arrive as literal text. Stripped from the text body and dispatched as voice (audio extensions) or document, matching the convention other Hermes adapters use.
Text-burst batching None. A user pasting a multi-line prompt produces N separate MessageEvents, and only the first reaches the agent before the rest get queued/dropped. HERMES_SIMPLEX_TEXT_BATCH_DELAY (default 0.8s). Rapid-fire inbound texts within the quiet window are concatenated into one MessageEvent — same pattern as Telegram's text batching.
Auto-accept contact requests Not handled — contactRequest events are silently ignored, so every new contact has to be approved manually. SIMPLEX_AUTO_ACCEPT (default true). Disable explicitly to gate every new contact behind an allowlist.
Send path: groups cmd_str = f"#[{group_id}] {content}". This silently doesn't deliver in production unless the group's display name is literally the numeric ID — the daemon parses #[...] as display-name lookup. Confirmed by sending messages to group:1 (display name Victoria-H) and watching them never arrive in the chat while the gateway reported "Sending response (... chars) to group:1". cmd_str = f"/_send #{group_id} json [...]". Structured form; addresses by numeric ID; json.dumps escapes newlines and quotes correctly.
Send path: DMs cmd_str = f"@[{chat_id}] {content}" — also bracket form. cmd_str = f"@{chat_id} {content}" — bare form, matches what's worked in production for months.

Test changes

test_send_dm and test_send_group previously asserted the bracket form. Both expectations were updated to match the formats above; this is in the same commit so the suite still passes 27/27.

If you'd rather keep the bracket-form expectations, the daemon-side parser is the place to fix it — a #[ID] text payload addressed by numeric ID would Just Work and would be consistent with the rest of the plugin's /_send calls. Happy to follow that thread separately.

What's not in this PR

  • The original out-of-tree adapter had a deeper integration with tools/send_message_tool for out-of-process (cron) sends including media. The plugin's standalone_sender_fn contract is text-only, and that's preserved here. If we want media for hermes cron running as a separate process from hermes gateway, that's a follow-up that probably belongs in the plugin contract.
  • New env vars are surfaced in plugin.yaml (version bumped to 1.1.0) and documented in website/docs/user-guide/messaging/simplex.md.

Test plan

  • pytest tests/gateway/test_simplex_plugin.py — 27 passed
  • Production: running on victoria continuously against simplex-chat 6.4 since March 2026 in its core-modifying form, and since 2026-05-18 in this plugin form. Tests cover:
    • DM inbound + outbound (text, images, voice notes, documents)
    • Group inbound + outbound (text, voice digest delivery via deliver=simplex)
    • XFTP inbound voice messages, deferred replay via rcvFileComplete
    • Outbound voice notes from TTS pipeline via MEDIA:<path> tags
    • Text-burst batching from multi-line paste
    • Auto-accept of incoming contact requests

The bracket-form regression I mentioned above was caught the same day we deployed this PR's branch and is the reason the send paths look the way they do here.

@alt-glitch alt-glitch added type/feature New feature or request comp/plugins Plugin system and bundled plugins comp/gateway Gateway runner, session dispatch, delivery P3 Low — cosmetic, nice to have labels May 18, 2026
@jooray
jooray force-pushed the feature/simplex-plugin branch from 205e59c to 6d3b391 Compare May 19, 2026 08:05
@jooray
jooray force-pushed the feature/simplex-plugin branch 2 times, most recently from b457790 to 82b1c5a Compare May 28, 2026 20:33
brandon-btcgroup added a commit to brandon-btcgroup/hermes-agent that referenced this pull request May 29, 2026
…emon

Four independent bugs prevented end-to-end SimpleX messaging against a
real simplex-chat daemon:

1. WS listener never sent /_start, so the daemon stored inbound
   messages but never pushed events to the subscriber.
2. newChatItems batch events nest `chatItems` under `resp`, not at the
   top level — every batched message was silently dropped.
3. Group sender was read from the legacy `chatItemMember` key; current
   simplex-chat reports it under `chatItem.chatDir.groupMember`, so
   sender_id fell back to the chat_id and failed allowlist matching.
   Falls back to chatItemMember for older payloads.
4. Outbound send used `@[id]`/`#[id]` bracket syntax the daemon reads
   as a literal contact name; switched to the `/_send @id text` /
   `/_send #id text` API form in both send() and _standalone_send().

Bugs 1, 2 and 4 mirror upstream PR NousResearch#26433 (issue NousResearch#30150). Bug 3 is not
covered there; the chatDir.groupMember approach matches PRs NousResearch#4666/NousResearch#27978.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
brandon-btcgroup added a commit to brandon-btcgroup/hermes-agent that referenced this pull request May 30, 2026
Switch send() and _standalone_send() from the /_send <ref> text shorthand
to the structured /_send <ref> json <ComposedMessage[]> form for both group
and DM sends. The text shorthand truncates the body at the first newline, so
multi-line agent replies were silently cut off; the json form escapes
newlines, backslashes and other special characters correctly.

This also aligns outbound text with the approach taken upstream in NousResearch#4666 /
NousResearch#27978, easing a future rebase. Adds a regression test asserting a multi-line
body is escaped rather than truncated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
brandon-btcgroup added a commit to brandon-btcgroup/hermes-agent that referenced this pull request May 30, 2026
…ening

Adds a 2026-05-29 part-2 update: sender fix upstreamed as issue NousResearch#35045 / PR
NousResearch#35046; rationale for NOT opening a group-send PR (already covered by
NousResearch#4666/NousResearch#27978 with a more robust json form); production branch hardened to
the /_send <ref> json form (commit d31a043) to stop multi-line reply
truncation; and a rebase note for the eventual NousResearch#26433 merge conflict.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extends the SimpleX Chat platform plugin (NousResearch#27???) with the features we
had been carrying out-of-tree against the older core-modifying SimpleX
integration. All additions live entirely inside
``plugins/platforms/simplex/`` — no edits to any core file — and pass
the existing ``tests/gateway/test_simplex_plugin.py`` suite unchanged.

What's new

- **Group support** via ``SIMPLEX_GROUP_ALLOWED``. Comma-separated group
  IDs, or ``*`` for any. Omitted (default) keeps the safer behavior of
  ignoring group messages entirely — a bot in a group otherwise
  processes every member's traffic. Inbound items from groups are
  surfaced with ``chat_id="group:<id>"`` and ``chat_type="group"``.

- **Real inbound file/voice ingestion** via the daemon's XFTP flow.
  On ``rcvFileDescrReady`` we send ``/freceive`` immediately so the
  download starts; voice notes whose file hasn't landed yet are
  deferred (``_pending_file_transfers``) and replayed once
  ``rcvFileComplete`` fires. The previous "sleep 2s and scan
  ``~/Downloads``" stub was race-prone on large files. Files are
  classified by extension into image / audio / document and emitted as
  ``MessageType.PHOTO`` / ``VOICE`` / ``TEXT + document``.

- **Real outbound attachments**: ``send_image`` (including ``file://``
  and ``http(s)://`` URLs with Pillow / ImageMagick conversion + inline
  thumbnail), ``send_image_file``, ``send_voice`` (native voice notes
  via ``msgContent.type="voice"``), ``send_video``, ``send_document``.
  All use the structured ``/_send … json`` form addressed by numeric ID
  so groups with non-unique display names don't get the wrong target.
  Agent replies may also embed ``MEDIA:<path>`` tags which the adapter
  strips from the text and dispatches as voice or document depending
  on extension.

- **Text-burst batching** (``HERMES_SIMPLEX_TEXT_BATCH_DELAY``, default
  0.8s). Rapid-fire inbound text messages within the quiet window are
  concatenated into one ``MessageEvent`` before reaching the agent —
  same pattern as Telegram's text batching. Prevents the gateway from
  dropping all-but-the-first message when a user pastes a multi-line
  prompt.

- **Auto-accept contact requests** (``SIMPLEX_AUTO_ACCEPT``, default
  ``true``). Incoming ``contactRequest`` events trigger
  ``/accept <id>``. Disable explicitly if you want to gate every new
  contact behind an allowlist.

- **Send / fire-and-forget split**. ``send()`` is now fire-and-forget
  at the WebSocket level — text replies don't serialise behind a
  30-second timeout when the daemon skips the corr-id reply. The
  ``_send_command`` path with corr-id tracking is reserved for
  media commands where we genuinely need acknowledgement. The bracket
  form ``@[<id>]`` / ``#[<id>]`` is used for single-line text;
  multi-line content drops to ``/_send … json`` so newlines survive
  the daemon's command parser.

Plugin manifest

``plugin.yaml`` bumps to ``1.1.0`` and surfaces the new env vars
(``SIMPLEX_AUTO_ACCEPT``, ``SIMPLEX_GROUP_ALLOWED``,
``HERMES_SIMPLEX_TEXT_BATCH_DELAY``) in the ``hermes config`` UI.
``_env_enablement`` seeds matching keys into ``PlatformConfig.extra``
so env-only setups show up in ``hermes gateway status`` without
instantiating the WebSocket client.

Docs

``website/docs/user-guide/messaging/simplex.md`` documents the new env
vars, the group-chat addressing scheme, and the inbound/outbound
attachment behaviour.

Compatibility

All 27 existing ``tests/gateway/test_simplex_plugin.py`` tests pass
unchanged: ``_make_corr_id`` still tracks ``_pending_corr_ids`` with
the same trim invariant, ``send()`` still produces ``@[<id>]`` /
``#[<id>]`` for single-line text, ``_standalone_send`` keeps its
text-only contract, and ``register()`` retains the same kwargs.
@jooray
jooray force-pushed the feature/simplex-plugin branch from 82b1c5a to 3d08a34 Compare May 30, 2026 07:45
@lambertian

lambertian commented May 30, 2026

Copy link
Copy Markdown

+1 on the WS-native direction. One empirical data point on the recurring "does the -p daemon actually push inbound events, or do we have to poll?" question — since the parallel polling PRs (#26433, the #30150 thread) assume it doesn't, and that's a genuinely easy assumption to land on.

Tested against simplex-chat v6.5.1.1: it does push. With a single passive WebSocket client connected (nothing else talking to the daemon) and no /_start or any command sent, an inbound DM arrived on its own as an async {"resp":{"type":"newChatItems",...}} frame within a couple of seconds. Sending /_start afterward just returned chatRunning — a no-op, since the controller already runs under -p — and the next message pushed the same way. So native push works and /_start isn't the trigger, at least on v6.5.1.1.

The reason it so easily looks like the daemon doesn't push: items are nested under resp, so a handler reading chatItems at the top level gets nothing and silently drops every pushed event — a perfectly-pushing daemon looks silent, and polling becomes the natural workaround. (Easy one to miss.) Consuming the events the way this PR does, instead of bolting on a DB//tail poller, looks like the right direction.

One note for the end-to-end file path: this PR adds the adapter-side media methods, but the send_message_tool tool-layer still has to route media_files to them (its in-process branch currently calls adapter.send() text-only). That tool-layer routing looks already handled by #18686 / #23770 — so this PR plus one of those should close the loop for tool/cron file sends.

@lambertian

lambertian commented May 30, 2026

Copy link
Copy Markdown

A follow-up from a deeper read of the SimpleX adapter (alongside the inbound-document fix in #35490). Four issues land in regions this PR rewrites — documenting them here, and I've since opened standalone PRs for each against current main:

  1. Inbound message_id is never set (fix(simplex): populate inbound message_id from chat item itemId #35556). The MessageEvent(...) build doesn't populate message_id from meta.itemId, so reply-anchoring, the [Replying to: …] disambiguation prefix, and transcript-id features silently no-op on SimpleX. The one-line set is message_id=str(meta.get("itemId")) if meta.get("itemId") is not None else None (the None-guard matters — otherwise you get the literal "None"). This covers transcript-id + reply anchoring; native threaded replies would also need send() to honor reply_to.

  2. send() doesn't chunk long messages (fix(simplex): chunk long outbound messages in send() #35558). The adapter advertises a max message length, but the reply path passes full content straight to send(); every other text adapter self-chunks via truncate_message. A truncate_message(content, MAX_LEN) loop in send() keeps long replies (and code-fence-aware splitting) intact.

  3. Non-retryable handshake failures retry forever (fix(simplex): escalate non-retryable WebSocket handshake rejections instead of looping forever #35557). A handshake 4xx (e.g. a permanently misconfigured daemon) falls into the generic reconnect arm and busy-loops with no gateway-visible fatal state. An except InvalidStatus arm (or InvalidStatusCode on older websockets) that calls _set_fatal_error(..., retryable=False) before breaking matches the IRC adapter's pattern.

  4. Null-unsafe groupProfile / member-profile .get(..., {}) (fix(simplex): avoid AttributeError when an inbound group profile is null #35521). The group-name and sender-profile lookups do .get("groupProfile", {}).get(...), which raises on a daemon-emitted "groupProfile": null (the {} default only applies to a missing key, not a present-null one). The same (... or {}) guard is needed wherever this code lands.

This PR rewrites these same regions but doesn't address any of the four, so they're complementary, not duplicates — cross-linking so the overlap is visible and whoever merges second has the context.

teknium1 pushed a commit that referenced this pull request Jun 9, 2026
Salvage of PR #27978 cherry-picked onto current main, resolving conflicts
with main's intervening SimpleX plugin fixes (resp-envelope normalization,
health-monitor reconnect-churn fix, bare-form DM addressing).

What's new:
- Group support via SIMPLEX_GROUP_ALLOWED (comma-separated IDs or '*');
  inbound items surface chat_id=group:<id> + chat_type=group. Disabled by
  default so a bot in a group doesn't process every member's traffic.
- Inbound files/voice via rcvFileDescrReady (immediate /freceive) deferred
  through _pending_file_transfers, replayed on rcvFileComplete. Voice notes
  -> MessageType.VOICE.
- Native outbound media: send_image (PNG/JPEG + inline thumbnail), send_voice
  (msgContent.type=voice), send_video, send_document. All addressed by numeric
  ID via /_send ... json [...].
- MEDIA:<path> tags in agent replies stripped and dispatched as voice/document.
- Text-burst batching (HERMES_SIMPLEX_TEXT_BATCH_DELAY, default 0.8s).
- Auto-accept contact requests (SIMPLEX_AUTO_ACCEPT, default true).
- Group send path uses structured /_send #<id> json form (the bracket
  #[<id>] form is parsed as display-name lookup and silently drops).

plugin.yaml bumped to 1.1.0; docs updated. All inside plugins/platforms/simplex/
- no core edits.

Co-authored-by: Juraj Bednar <juraj@bednar.io>
@jooray
jooray deleted the feature/simplex-plugin branch June 9, 2026 11:07
changman pushed a commit to changman/hermes-agent that referenced this pull request Jun 10, 2026
Salvage of PR NousResearch#27978 cherry-picked onto current main, resolving conflicts
with main's intervening SimpleX plugin fixes (resp-envelope normalization,
health-monitor reconnect-churn fix, bare-form DM addressing).

What's new:
- Group support via SIMPLEX_GROUP_ALLOWED (comma-separated IDs or '*');
  inbound items surface chat_id=group:<id> + chat_type=group. Disabled by
  default so a bot in a group doesn't process every member's traffic.
- Inbound files/voice via rcvFileDescrReady (immediate /freceive) deferred
  through _pending_file_transfers, replayed on rcvFileComplete. Voice notes
  -> MessageType.VOICE.
- Native outbound media: send_image (PNG/JPEG + inline thumbnail), send_voice
  (msgContent.type=voice), send_video, send_document. All addressed by numeric
  ID via /_send ... json [...].
- MEDIA:<path> tags in agent replies stripped and dispatched as voice/document.
- Text-burst batching (HERMES_SIMPLEX_TEXT_BATCH_DELAY, default 0.8s).
- Auto-accept contact requests (SIMPLEX_AUTO_ACCEPT, default true).
- Group send path uses structured /_send #<id> json form (the bracket
  #[<id>] form is parsed as display-name lookup and silently drops).

plugin.yaml bumped to 1.1.0; docs updated. All inside plugins/platforms/simplex/
- no core edits.

Co-authored-by: Juraj Bednar <juraj@bednar.io>
changman pushed a commit to changman/hermes-agent that referenced this pull request Jun 10, 2026
alt-glitch pushed a commit that referenced this pull request Jun 14, 2026
Salvage of PR #27978 cherry-picked onto current main, resolving conflicts
with main's intervening SimpleX plugin fixes (resp-envelope normalization,
health-monitor reconnect-churn fix, bare-form DM addressing).

What's new:
- Group support via SIMPLEX_GROUP_ALLOWED (comma-separated IDs or '*');
  inbound items surface chat_id=group:<id> + chat_type=group. Disabled by
  default so a bot in a group doesn't process every member's traffic.
- Inbound files/voice via rcvFileDescrReady (immediate /freceive) deferred
  through _pending_file_transfers, replayed on rcvFileComplete. Voice notes
  -> MessageType.VOICE.
- Native outbound media: send_image (PNG/JPEG + inline thumbnail), send_voice
  (msgContent.type=voice), send_video, send_document. All addressed by numeric
  ID via /_send ... json [...].
- MEDIA:<path> tags in agent replies stripped and dispatched as voice/document.
- Text-burst batching (HERMES_SIMPLEX_TEXT_BATCH_DELAY, default 0.8s).
- Auto-accept contact requests (SIMPLEX_AUTO_ACCEPT, default true).
- Group send path uses structured /_send #<id> json form (the bracket
  #[<id>] form is parsed as display-name lookup and silently drops).

plugin.yaml bumped to 1.1.0; docs updated. All inside plugins/platforms/simplex/
- no core edits.

Co-authored-by: Juraj Bednar <juraj@bednar.io>
davidgut1982 pushed a commit to davidgut1982/hermes-agent that referenced this pull request Jun 17, 2026
Salvage of PR NousResearch#27978 cherry-picked onto current main, resolving conflicts
with main's intervening SimpleX plugin fixes (resp-envelope normalization,
health-monitor reconnect-churn fix, bare-form DM addressing).

What's new:
- Group support via SIMPLEX_GROUP_ALLOWED (comma-separated IDs or '*');
  inbound items surface chat_id=group:<id> + chat_type=group. Disabled by
  default so a bot in a group doesn't process every member's traffic.
- Inbound files/voice via rcvFileDescrReady (immediate /freceive) deferred
  through _pending_file_transfers, replayed on rcvFileComplete. Voice notes
  -> MessageType.VOICE.
- Native outbound media: send_image (PNG/JPEG + inline thumbnail), send_voice
  (msgContent.type=voice), send_video, send_document. All addressed by numeric
  ID via /_send ... json [...].
- MEDIA:<path> tags in agent replies stripped and dispatched as voice/document.
- Text-burst batching (HERMES_SIMPLEX_TEXT_BATCH_DELAY, default 0.8s).
- Auto-accept contact requests (SIMPLEX_AUTO_ACCEPT, default true).
- Group send path uses structured /_send #<id> json form (the bracket
  #[<id>] form is parsed as display-name lookup and silently drops).

plugin.yaml bumped to 1.1.0; docs updated. All inside plugins/platforms/simplex/
- no core edits.

Co-authored-by: Juraj Bednar <juraj@bednar.io>
davidgut1982 pushed a commit to davidgut1982/hermes-agent that referenced this pull request Jun 17, 2026
T02200059 pushed a commit to T02200059/hermes-agent that referenced this pull request Jun 18, 2026
Salvage of PR NousResearch#27978 cherry-picked onto current main, resolving conflicts
with main's intervening SimpleX plugin fixes (resp-envelope normalization,
health-monitor reconnect-churn fix, bare-form DM addressing).

What's new:
- Group support via SIMPLEX_GROUP_ALLOWED (comma-separated IDs or '*');
  inbound items surface chat_id=group:<id> + chat_type=group. Disabled by
  default so a bot in a group doesn't process every member's traffic.
- Inbound files/voice via rcvFileDescrReady (immediate /freceive) deferred
  through _pending_file_transfers, replayed on rcvFileComplete. Voice notes
  -> MessageType.VOICE.
- Native outbound media: send_image (PNG/JPEG + inline thumbnail), send_voice
  (msgContent.type=voice), send_video, send_document. All addressed by numeric
  ID via /_send ... json [...].
- MEDIA:<path> tags in agent replies stripped and dispatched as voice/document.
- Text-burst batching (HERMES_SIMPLEX_TEXT_BATCH_DELAY, default 0.8s).
- Auto-accept contact requests (SIMPLEX_AUTO_ACCEPT, default true).
- Group send path uses structured /_send #<id> json form (the bracket
  #[<id>] form is parsed as display-name lookup and silently drops).

plugin.yaml bumped to 1.1.0; docs updated. All inside plugins/platforms/simplex/
- no core edits.

Co-authored-by: Juraj Bednar <juraj@bednar.io>
T02200059 pushed a commit to T02200059/hermes-agent that referenced this pull request Jun 18, 2026
xyshanren pushed a commit to xyshanren/hermes-agent-cn that referenced this pull request Jun 25, 2026
waefrebeorn pushed a commit to waefrebeorn/slermes that referenced this pull request Jul 2, 2026
Salvage of PR NousResearch#27978 cherry-picked onto current main, resolving conflicts
with main's intervening SimpleX plugin fixes (resp-envelope normalization,
health-monitor reconnect-churn fix, bare-form DM addressing).

What's new:
- Group support via SIMPLEX_GROUP_ALLOWED (comma-separated IDs or '*');
  inbound items surface chat_id=group:<id> + chat_type=group. Disabled by
  default so a bot in a group doesn't process every member's traffic.
- Inbound files/voice via rcvFileDescrReady (immediate /freceive) deferred
  through _pending_file_transfers, replayed on rcvFileComplete. Voice notes
  -> MessageType.VOICE.
- Native outbound media: send_image (PNG/JPEG + inline thumbnail), send_voice
  (msgContent.type=voice), send_video, send_document. All addressed by numeric
  ID via /_send ... json [...].
- MEDIA:<path> tags in agent replies stripped and dispatched as voice/document.
- Text-burst batching (HERMES_SIMPLEX_TEXT_BATCH_DELAY, default 0.8s).
- Auto-accept contact requests (SIMPLEX_AUTO_ACCEPT, default true).
- Group send path uses structured /_send #<id> json form (the bracket
  #[<id>] form is parsed as display-name lookup and silently drops).

plugin.yaml bumped to 1.1.0; docs updated. All inside plugins/platforms/simplex/
- no core edits.

Co-authored-by: Juraj Bednar <juraj@bednar.io>
waefrebeorn pushed a commit to waefrebeorn/slermes that referenced this pull request Jul 2, 2026
santhreal pushed a commit to santhreal/hermes-agent that referenced this pull request Jul 13, 2026
Salvage of PR NousResearch#27978 cherry-picked onto current main, resolving conflicts
with main's intervening SimpleX plugin fixes (resp-envelope normalization,
health-monitor reconnect-churn fix, bare-form DM addressing).

What's new:
- Group support via SIMPLEX_GROUP_ALLOWED (comma-separated IDs or '*');
  inbound items surface chat_id=group:<id> + chat_type=group. Disabled by
  default so a bot in a group doesn't process every member's traffic.
- Inbound files/voice via rcvFileDescrReady (immediate /freceive) deferred
  through _pending_file_transfers, replayed on rcvFileComplete. Voice notes
  -> MessageType.VOICE.
- Native outbound media: send_image (PNG/JPEG + inline thumbnail), send_voice
  (msgContent.type=voice), send_video, send_document. All addressed by numeric
  ID via /_send ... json [...].
- MEDIA:<path> tags in agent replies stripped and dispatched as voice/document.
- Text-burst batching (HERMES_SIMPLEX_TEXT_BATCH_DELAY, default 0.8s).
- Auto-accept contact requests (SIMPLEX_AUTO_ACCEPT, default true).
- Group send path uses structured /_send #<id> json form (the bracket
  #[<id>] form is parsed as display-name lookup and silently drops).

plugin.yaml bumped to 1.1.0; docs updated. All inside plugins/platforms/simplex/
- no core edits.

Co-authored-by: Juraj Bednar <juraj@bednar.io>
santhreal pushed a commit to santhreal/hermes-agent that referenced this pull request Jul 13, 2026
donbowman pushed a commit to donbowman/hermes-agent that referenced this pull request Jul 13, 2026
Salvage of PR NousResearch#27978 cherry-picked onto current main, resolving conflicts
with main's intervening SimpleX plugin fixes (resp-envelope normalization,
health-monitor reconnect-churn fix, bare-form DM addressing).

What's new:
- Group support via SIMPLEX_GROUP_ALLOWED (comma-separated IDs or '*');
  inbound items surface chat_id=group:<id> + chat_type=group. Disabled by
  default so a bot in a group doesn't process every member's traffic.
- Inbound files/voice via rcvFileDescrReady (immediate /freceive) deferred
  through _pending_file_transfers, replayed on rcvFileComplete. Voice notes
  -> MessageType.VOICE.
- Native outbound media: send_image (PNG/JPEG + inline thumbnail), send_voice
  (msgContent.type=voice), send_video, send_document. All addressed by numeric
  ID via /_send ... json [...].
- MEDIA:<path> tags in agent replies stripped and dispatched as voice/document.
- Text-burst batching (HERMES_SIMPLEX_TEXT_BATCH_DELAY, default 0.8s).
- Auto-accept contact requests (SIMPLEX_AUTO_ACCEPT, default true).
- Group send path uses structured /_send #<id> json form (the bracket
  #[<id>] form is parsed as display-name lookup and silently drops).

plugin.yaml bumped to 1.1.0; docs updated. All inside plugins/platforms/simplex/
- no core edits.

Co-authored-by: Juraj Bednar <juraj@bednar.io>
donbowman pushed a commit to donbowman/hermes-agent that referenced this pull request Jul 13, 2026
Gravezzz pushed a commit to Gravezzz/hermes-agent that referenced this pull request Jul 21, 2026
Salvage of PR NousResearch#27978 cherry-picked onto current main, resolving conflicts
with main's intervening SimpleX plugin fixes (resp-envelope normalization,
health-monitor reconnect-churn fix, bare-form DM addressing).

What's new:
- Group support via SIMPLEX_GROUP_ALLOWED (comma-separated IDs or '*');
  inbound items surface chat_id=group:<id> + chat_type=group. Disabled by
  default so a bot in a group doesn't process every member's traffic.
- Inbound files/voice via rcvFileDescrReady (immediate /freceive) deferred
  through _pending_file_transfers, replayed on rcvFileComplete. Voice notes
  -> MessageType.VOICE.
- Native outbound media: send_image (PNG/JPEG + inline thumbnail), send_voice
  (msgContent.type=voice), send_video, send_document. All addressed by numeric
  ID via /_send ... json [...].
- MEDIA:<path> tags in agent replies stripped and dispatched as voice/document.
- Text-burst batching (HERMES_SIMPLEX_TEXT_BATCH_DELAY, default 0.8s).
- Auto-accept contact requests (SIMPLEX_AUTO_ACCEPT, default true).
- Group send path uses structured /_send #<id> json form (the bracket
  #[<id>] form is parsed as display-name lookup and silently drops).

plugin.yaml bumped to 1.1.0; docs updated. All inside plugins/platforms/simplex/
- no core edits.

Co-authored-by: Juraj Bednar <juraj@bednar.io>
Gravezzz pushed a commit to Gravezzz/hermes-agent that referenced this pull request Jul 21, 2026
leewenjie pushed a commit to leewenjie/hermes-agent that referenced this pull request Aug 7, 2026
Salvage of PR NousResearch#27978 cherry-picked onto current main, resolving conflicts
with main's intervening SimpleX plugin fixes (resp-envelope normalization,
health-monitor reconnect-churn fix, bare-form DM addressing).

What's new:
- Group support via SIMPLEX_GROUP_ALLOWED (comma-separated IDs or '*');
  inbound items surface chat_id=group:<id> + chat_type=group. Disabled by
  default so a bot in a group doesn't process every member's traffic.
- Inbound files/voice via rcvFileDescrReady (immediate /freceive) deferred
  through _pending_file_transfers, replayed on rcvFileComplete. Voice notes
  -> MessageType.VOICE.
- Native outbound media: send_image (PNG/JPEG + inline thumbnail), send_voice
  (msgContent.type=voice), send_video, send_document. All addressed by numeric
  ID via /_send ... json [...].
- MEDIA:<path> tags in agent replies stripped and dispatched as voice/document.
- Text-burst batching (HERMES_SIMPLEX_TEXT_BATCH_DELAY, default 0.8s).
- Auto-accept contact requests (SIMPLEX_AUTO_ACCEPT, default true).
- Group send path uses structured /_send #<id> json form (the bracket
  #[<id>] form is parsed as display-name lookup and silently drops).

plugin.yaml bumped to 1.1.0; docs updated. All inside plugins/platforms/simplex/
- no core edits.

Co-authored-by: Juraj Bednar <juraj@bednar.io>
leewenjie pushed a commit to leewenjie/hermes-agent that referenced this pull request Aug 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery comp/plugins Plugin system and bundled plugins 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.

3 participants