Skip to content

feat(sync): support bidirectional platform command sync (Issue #4) - #61169

Open
gigakun3030 wants to merge 4 commits into
NousResearch:mainfrom
gigakun3030:feat/platform-command-sync
Open

gigakun3030 wants to merge 4 commits into
NousResearch:mainfrom
gigakun3030:feat/platform-command-sync

Conversation

@gigakun3030

Copy link
Copy Markdown
Contributor

Implements true bidirectional command synchronization between Hermes config and connected messaging platforms.

Changes

Telegram adapter (plugins/platforms/telegram/adapter.py):

  • Add delete_my_commands(scope) before set_my_commands to clear stale entries
  • Filter commands by visibility config per-platform before registering
  • Stale/disabled commands now properly disappear from / menu

Discord adapter (plugins/platforms/discord/adapter.py):

  • Filter slash commands by visibility config before tree registration
  • Already used tree.sync() which is bidirectional — just needed visibility filter

New API:

  • POST /api/commands/sync — triggers re-registration on all connected platforms without gateway restart
  • Dashboard 'Sync to Platforms' button in CommandsPage

Tested on Linux with Telegram and Discord.

@alt-glitch alt-glitch added type/feature New feature or request comp/gateway Gateway runner, session dispatch, delivery comp/cli CLI entry point, hermes_cli/, setup wizard comp/dashboard Web dashboard / control panel UI (dashboard/, landing) platform/telegram Telegram bot adapter platform/discord Discord bot adapter P3 Low — cosmetic, nice to have sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages labels Jul 8, 2026

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for tackling platform command reconciliation. Current main has registry-derived Telegram menus (plugins/platforms/telegram/adapter.py:2923-2943) and safe Discord reconciliation (plugins/platforms/discord/adapter.py:1867-1939), but not this config-driven management surface.

Problems

  • Profile selection is lost for custom writes and sync: web/src/lib/api.ts:1202,1222 sends profile in JSON, while hermes_cli/web_server.py:9886,10007 accepts it as a query parameter. Those actions therefore use the dashboard process's current profile.
  • plugins/platforms/telegram/adapter.py:2850 deletes the existing menu before set_my_commands; a caught replacement failure at line 2855 leaves that scope empty.
  • The PR persists visible.cli (hermes_cli/web_server.py:9904) without changing the CLI or TUI dispatch paths, which still read quick_commands (cli.py:8918, tui_gateway/server.py:11665).
  • The 12 changed files include no tests.

Suggested changes

  • Carry and validate profile consistently, then select the correct standalone or multiplexed adapter set.
  • Do not pre-delete Telegram menus; preserve the prior menu on replacement failure.
  • Define the CLI/TUI visibility contract and add profile, sync, migration, and failure-path coverage.

Automated hermes-sweeper review.

Comment thread web/src/lib/api.ts Outdated
fetchJSON<{ ok: boolean }>("/api/commands/custom", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ ...command, profile: profile || undefined }),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sends profile in the JSON body, but upsert_custom_command(..., profile: Optional[str] = None) binds profile from the query string and CustomCommandInput has no profile field. Editing a selected non-current profile will write the dashboard process's current profile instead; use profileQuery(profile) or add an explicit validated body field.

Comment thread hermes_cli/web_server.py


@app.post("/api/commands/sync")
async def sync_platform_commands(profile: Optional[str] = None):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sync endpoint accepts profile but never scopes config/PID lookup or chooses that profile's adapters. The client also sends the value in JSON rather than the query string. This can sync the default/current gateway after editing another profile; resolve the requested profile and support GatewayRunner._profile_adapters for multiplexed gateways.

Comment thread plugins/platforms/telegram/adapter.py Outdated
scope_name = getattr(scope_cls, "__name__", str(scope_cls))
try:
try:
await self._bot.delete_my_commands(scope=scope_cls())

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not clear the current menu before its replacement succeeds. If set_my_commands raises at line 2853, the outer handler logs and continues after the scope was already emptied. Calling set_my_commands directly preserves the previous menu when the replacement request fails.

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-platform-windows Sweeper risk: may break or behave differently on native Windows sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 10, 2026
- Fix NousResearch#1: api.ts sends profile as query param, not in JSON body
- Fix NousResearch#2: Telegram adapter no longer delete_my_commands before set_my_commands
- Fix NousResearch#3: CLI dispatch reads commands.custom with visible.cli gate
- Fix NousResearch#3: Gateway dispatch resolves alias from commands.custom
- Fix NousResearch#4: Add regression tests for profile routing, CRUD, migration, failures, visible.cli

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard comp/dashboard Web dashboard / control panel UI (dashboard/, landing) comp/gateway Gateway runner, session dispatch, delivery P3 Low — cosmetic, nice to have platform/discord Discord bot adapter platform/telegram Telegram bot adapter sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-platform-windows Sweeper risk: may break or behave differently on native Windows type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants