Skip to content

Telegram surface: DM turns, delivery polling, and a generalized core client - #196

Open
BeAChanger wants to merge 1 commit into
yc-software:mainfrom
BeAChanger:feat/telegram-surface
Open

Telegram surface: DM turns, delivery polling, and a generalized core client#196
BeAChanger wants to merge 1 commit into
yc-software:mainfrom
BeAChanger:feat/telegram-surface

Conversation

@BeAChanger

@BeAChanger BeAChanger commented Aug 4, 2026

Copy link
Copy Markdown

Summary

Adds Telegram as a first-class surface alongside Slack and the web:

  • src/telegram/ — a new in-process plugin mirroring the Slack one. Long-polls getUpdates (no public URL or TLS needed), bridges each DM message to a turn with surface: "telegram", posts the reply back to the same chat (threaded when replying to the bot), splits replies > 4096 chars, and claims type: "telegram" deliveries for cron / monitor / agent-initiated posts (including file documents). Group chats are refused out loud rather than mis-scoped; DM-only for now.
  • Core generalizationsrc/api/slack-core-client.tssrc/api/core-client.ts: createCoreClient(deps, surface) parameterizes the surface name (default "slack"), and the turn bridge moved to src/api/core-bridge.ts so both surfaces share one implementation. wiring.ts now exposes telegramCore alongside slackCore; src/index.ts boots the plugin when TELEGRAM_BOT_TOKEN is set.

Why

QM's core speaks surfaces generically — TurnRequest.surface flows into session scoping, delivery destination.type, and the surface tool name (the pi-tools test already asserts a telegram surface produces a telegram tool). Only the Slack plugin's client was hard-coded to "slack", which blocked a second surface. This change removes that coupling and demonstrates the pattern with a working Telegram surface.

Setup

BotFather → /newbot → put the token in TELEGRAM_BOT_TOKEN. Optional TELEGRAM_ALLOWED_CHAT_IDS to restrict which chats the bot answers. See src/telegram/README.md.

Test plan

  • test/telegram-plugin.test.ts (new): mocks the Bot API via an injected fetchImpl and covers message→turn→reply, long-reply splitting, reply-thread continuation, chat allowlisting, delivery claim/ack, and the surface parameterization.
  • test/slack-index.integration.test.ts and the other slack/delivery suites: all still green (216 + 116 tests run locally).
  • tsc --noEmit, eslint, prettier --check, and the root-test-shard plan check all pass.

Screenshot: no UI surface — this is a headless plugin; behavior is covered by the tests above.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

…lized core client

The Slack plugin's core client hard-coded the "slack" surface name, so a
second in-process surface had nowhere to stand. Parameterize the client
(createCoreClient(deps, surface)) and move the turn bridge into src/api so
both surfaces share it.

The new src/telegram plugin mirrors the Slack one: long-poll getUpdates for
inbound messages, POST turns with surface "telegram", reply into the same
chat (threaded when replying to the bot), and claim type "telegram"
deliveries for cron/monitor/agent-initiated posts. DM-only for now; group
chats are refused out loud rather than mis-scoped.

Tests mock the Bot API via an injected fetch and exercise the full path:
message to turn, reply posting, long-reply splitting, reply-thread
continuation, chat allowlisting, delivery claim/ack, and the surface
parameterization itself.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant