feat(sync): support bidirectional platform command sync (Issue #4) - #61169
gigakun3030 wants to merge 4 commits into
Conversation
teknium1
left a comment
There was a problem hiding this comment.
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,1222sendsprofilein JSON, whilehermes_cli/web_server.py:9886,10007accepts it as a query parameter. Those actions therefore use the dashboard process's current profile. plugins/platforms/telegram/adapter.py:2850deletes the existing menu beforeset_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 readquick_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.
| fetchJSON<{ ok: boolean }>("/api/commands/custom", { | ||
| method: "POST", | ||
| headers: { "Content-Type": "application/json" }, | ||
| body: JSON.stringify({ ...command, profile: profile || undefined }), |
There was a problem hiding this comment.
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.
|
|
||
|
|
||
| @app.post("/api/commands/sync") | ||
| async def sync_platform_commands(profile: Optional[str] = None): |
There was a problem hiding this comment.
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.
| scope_name = getattr(scope_cls, "__name__", str(scope_cls)) | ||
| try: | ||
| try: | ||
| await self._bot.delete_my_commands(scope=scope_cls()) |
There was a problem hiding this comment.
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.
- 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
Implements true bidirectional command synchronization between Hermes config and connected messaging platforms.
Changes
Telegram adapter (plugins/platforms/telegram/adapter.py):
Discord adapter (plugins/platforms/discord/adapter.py):
New API:
Tested on Linux with Telegram and Discord.