Skip to content

feat(telegram): let plugins handle callback queries and send markup - #96053

Open
vKongv wants to merge 1 commit into
NousResearch:mainfrom
pebble-tech:feat/telegram-plugin-callback-handlers
Open

feat(telegram): let plugins handle callback queries and send markup#96053
vKongv wants to merge 1 commit into
NousResearch:mainfrom
pebble-tech:feat/telegram-plugin-callback-handlers

Conversation

@vKongv

@vKongv vKongv commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Plugins can register Telegram inline-keyboard handlers the same way they register Slack action handlers, and they can attach those keyboards through adapter.send() metadata.

Without this, a plugin that sends InlineKeyboardMarkup has its callback_query swallowed by the built-in prefix router. The alternatives are forking the adapter or adding a second PTB CallbackQueryHandler, which reconnect rebuilds drop.

This PR:

  • Adds PluginContext.register_telegram_callback_handler(prefix, callback) and queues (prefix, callback, plugin_name) on PluginManager.
  • Dispatches inside the existing _handle_callback_query after built-in prefixes, using longest-prefix match. Built-in prefixes stay reserved and cannot be overridden.
  • Authorizes the tapper, always query.answer()s on a match, and swallows handler exceptions.
  • Prefers set_authorization_check / _is_sender_authorized before the bound-handler __self__ lookup, so multiplex_profiles closures do not fail-closed on empty env allowlists (same class as Telegram group_allowed_chats is skipped by early auth with multiplex handler closures #87132 / [Bug]: Telegram inline callbacks reject profile-authorized users under multiplex routing #86296).
  • Extends TelegramAdapter.send(..., metadata) with reply_markup (structured rows or pass-through markup) and optional per-send disable_link_preview. Keyboard attaches to the first chunk only when the message is split. If markup is present, the rich-send path is skipped so the keyboard is not dropped.

Related open work (searched before opening): #78619, #80458, #85565 take other plugin-callback shapes (gateway_platform_event or a lifecycle hook). This one stays on the Slack-style registry plus send metadata. #86308 is the multiplex callback-auth fix for built-in buttons.

Related Issue

Related to #87132 / #86296 (callback auth under multiplex). No dedicated issue for the registry API.

Type of Change

  • ✨ New feature (non-breaking change that adds functionality)
  • ✅ Tests (adding or improving test coverage)

Changes Made

  • hermes_cli/plugins.py: register / get / clear Telegram callback handlers; reject reserved prefixes
  • plugins/platforms/telegram/adapter.py: plugin dispatch, multiplex-safe callback auth, send markup and per-send preview override
  • tests/gateway/test_telegram_plugin_callback_handlers.py: register, dispatch, auth fail-closed, multiplex closure, built-in precedence, reconnect, send markup
  • tests/hermes_cli/test_plugins.py: force-rediscover clears the new list
  • website/docs/developer-guide/plugins/index.md: public API docs

How to Test

  1. scripts/run_tests.sh tests/gateway/test_telegram_plugin_callback_handlers.py tests/hermes_cli/test_plugins.py -q
  2. Register a plugin handler with ctx.register_telegram_callback_handler("task:", handler).
  3. Send a message with metadata={"reply_markup": [[{"text": "Go", "callback_data": "task:go"}]], "disable_link_preview": True}.
  4. Tap the button: built-ins still win; plugin prefix runs only for authorized users; unauthorized taps are answered and do not invoke the plugin.
  5. Under gateway.multiplex_profiles, a tap from an allowlisted user still reaches the plugin (authorization check is consulted even when the primary handler is a closure).

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: macOS 15.6

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings)
  • I've updated cli-config.yaml.example if I added/changed config keys — N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide
  • I've updated tool descriptions/schemas if I changed tool behavior — N/A

@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/cli CLI entry point, hermes_cli/, setup wizard comp/plugins Plugin system and bundled plugins platform/telegram Telegram bot adapter sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades needs-decision Awaiting maintainer decision before any implementation labels Aug 27, 2026
@cursor
cursor Bot force-pushed the feat/telegram-plugin-callback-handlers branch from 1fc3385 to f41a83f Compare August 27, 2026 10:45
@vKongv
vKongv force-pushed the feat/telegram-plugin-callback-handlers branch from f41a83f to 8216b89 Compare August 27, 2026 11:21
Plugins can register prefix-matched callback_query handlers and attach
inline keyboards or per-send preview overrides via send() metadata.
Callback auth prefers set_authorization_check so multiplex profile
closures do not fail-closed.
vKongv added a commit to pebble-tech/hermes-agent that referenced this pull request Aug 27, 2026
…CHES

Carry Nous NousResearch#96053 (KAI-157) on the next sync so plugin callback handlers and send() markup land on integration main.
@vKongv
vKongv force-pushed the feat/telegram-plugin-callback-handlers branch from 8216b89 to 29743c9 Compare August 27, 2026 14:04
vKongv added a commit to pebble-tech/hermes-agent that referenced this pull request Aug 27, 2026
…CHES

Carry Nous NousResearch#96053 (KAI-157) on the next sync so plugin callback handlers and send() markup land on integration main.
@teknium1

Copy link
Copy Markdown
Contributor

Heads-up: the handler-registration half of this landed in #59217 (34393c3) — ctx.register_platform_handler("telegram", factory) wires plugin CallbackQueryHandlers into the PTB Application before core handlers, so the swallowed-callback_query problem is solved on main. The outbound half (attaching InlineKeyboardMarkup via adapter.send metadata) is NOT covered and still worth reviewing — a rebase onto main that drops the handler plumbing and keeps the send-markup surface would slim this nicely.

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/plugins Plugin system and bundled plugins needs-decision Awaiting maintainer decision before any implementation P3 Low — cosmetic, nice to have platform/telegram Telegram bot adapter sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants