← Back to PRs

#23727: Fix Telegram channel resolution drift across announce + message send paths

by SmithLabsLLC open 2026-02-22 16:40 View on GitHub →
channel: telegram gateway commands agents size: M
## Summary - add a shared outbound channel resolver (`src/infra/outbound/channel-resolution.ts`) that: - normalizes explicit channel inputs with deliverable-channel rules - retries missing channel plugins by bootstrapping plugin registry from config (`applyPluginAutoEnable` + `loadOpenClawPlugins`) - wire announce/send paths to use that shared resolver: - `src/infra/outbound/targets.ts` (cron/subagent announce target resolution + heartbeat account/allowFrom checks) - `src/infra/outbound/message.ts` (message/send + poll explicit channel handling) - `src/gateway/server-methods/send.ts` (gateway `send`/`poll` channel plugin lookup) This keeps channel resolution behavior consistent and recovers from empty/stale plugin registries in these outbound paths, preventing Telegram from being rejected as unsupported/unknown. ## Regression tests - `src/infra/outbound/targets.channel-resolution.test.ts` - reproduces and guards against `Unsupported channel: telegram` in announce target resolution - `src/infra/outbound/message.test.ts` - reproduces and guards against `Unknown channel: telegram` in message/send ## Verification ```bash pnpm vitest src/infra/outbound/message.test.ts src/infra/outbound/targets.channel-resolution.test.ts src/infra/outbound/targets.test.ts src/gateway/server-methods/send.test.ts pnpm lint -- src/infra/outbound/channel-resolution.ts src/infra/outbound/message.ts src/infra/outbound/targets.ts src/gateway/server-methods/send.ts src/infra/outbound/message.test.ts src/infra/outbound/targets.channel-resolution.test.ts pnpm exec tsc --noEmit -p tsconfig.json --pretty false ``` Related: #21968 #21595 #13420 #14188 <!-- greptile_comment --> <h3>Greptile Summary</h3> This PR introduces a shared channel resolution module (`channel-resolution.ts`) that prevents Telegram and other plugins from being rejected as unsupported when the plugin registry is empty or stale. The fix applies consistently across announce/send paths by: - Creating `resolveOutboundChannelPlugin()` that normalizes channel inputs and retries plugin lookup after bootstrapping the plugin registry from config - Using a module-level `Set` to track bootstrap attempts per registry key, preventing infinite retry loops - Replacing direct `getChannelPlugin()` calls in `targets.ts`, `message.ts`, and `send.ts` with the new shared resolver The implementation includes regression tests that verify the bootstrap recovery mechanism works correctly for both announce target resolution and message send flows. <h3>Confidence Score: 5/5</h3> - This PR is safe to merge with minimal risk - The refactoring follows established patterns, includes comprehensive regression tests for both affected code paths, uses proper deduplication to prevent infinite loops, and maintains backward compatibility by wrapping existing functions without changing their signatures - No files require special attention <sub>Last reviewed commit: 4381ffe</sub> <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs