Skip to content

[Feat] Mock Telegram Bot API harness and routing confirmation for Telegram task entry - #22

Merged
daniel-lxs merged 1 commit into
developfrom
feat/telegram-mock-harness-and-routing-confirmation
Jul 9, 2026
Merged

[Feat] Mock Telegram Bot API harness and routing confirmation for Telegram task entry#22
daniel-lxs merged 1 commit into
developfrom
feat/telegram-mock-harness-and-routing-confirmation

Conversation

@daniel-lxs

Copy link
Copy Markdown
Member

What

Two related pieces that bring the Telegram integration up to Slack-grade testability and routing UX:

1. Mock Telegram Bot API harness (packages/communication)

  • MockTelegramServer — impersonates both halves of the Bot API: outbound methods (sendMessage, sendPhoto, editMessageText, reactions, inline keyboards, webhook registration) and inbound update dispatch (signed with the secret-token header) into the real /api/webhooks/telegram handler. Control plane at /mock/state + /mock/events, mirroring the mock Slack harness.
  • Enforces real Telegram limits (4096-char messages, unknown chats, missing reply targets) so regressions fail loudly, and auto-computes entities for injected text so bot-command/mention detection behaves exactly as in production.
  • TELEGRAM_API_BASE_URL env override (default https://api.telegram.org) reroutes every runtime provider construction — zero production impact.
  • CLI runner (pnpm --filter @roomote/communication mock:telegram), LLM-judged eval runner (eval:telegram-scenario) + three fixtures, and the mock-telegram-testing skill with a 16-scenario user-journey catalog.

2. Routing confirmation for Telegram task entry (apps/api)

Previously Telegram launched every routed task immediately, and router fallback silently launched into all repos — the only mis-route recovery was cancel.

Now (mirroring Slack's gate): when router confidence is < 0.95, the workspace was remapped, or all-repositories was picked while environments exist, task entry posts a compact ✅ Yes / ✖️ Nope card that auto-starts the suggestion after ~5s. Nope edits the same message into a workspace picker (environments + all repos + Nevermind, no timer). Router fallback shows the picker directly.

Mechanics: pending choice in Redis with one-shot GETDEL claim (click and timer can never both launch), 64-byte-safe callback data, requester-only clicks, Nope re-keys state so the timer can never fire a rejected suggestion, superseding requests invalidate stale cards, and any confirmation-plumbing failure falls back to immediate launch so tasks are never dropped. Suggestion-button launches skip the card. New TelegramCommunicationProvider.editMessageText (with HTML→plain fallback) finalizes cards in place.

Testing

  • 56 API handler tests (11 new for confirmation flows) + 17 harness tests + 59 env tests pass; repo-wide lint:fast, check-types:fast, knip clean.
  • Live end-to-end through the mock harness against the dev stack (real LLM router): card posted → Nope swapped it into the picker under a fresh id → the 5s timer no-op'd → Nevermind finalized the card — zero cloud jobs created.

Docs

.agent-guidance/features/telegram-integration.md (config, inbound flow, testing, parity notes) and the mock-telegram-testing skill updated in the same change.

🤖 Generated with Claude Code

…egram task entry

Testing harness (packages/communication):
- MockTelegramServer: fake Bot API (sendMessage, sendPhoto, editMessageText,
  reactions, buttons, webhooks) with /mock/state + /mock/events control plane
  and signed update dispatch into the real webhook handler. Enforces real
  Telegram limits (4096 chars, unknown chats, missing reply targets) and
  auto-computes entities so bot-command/mention detection matches production.
- TELEGRAM_API_BASE_URL env override reroutes every runtime provider
  construction to the harness (mirrors SLACK_API_BASE_URL).
- CLI runner (mock:telegram), LLM-judged eval runner (eval:telegram-scenario)
  with three scenario fixtures, and the mock-telegram-testing skill with a
  user-journey scenario catalog.

Routing confirmation (apps/api telegram handler):
- When the router is below 0.95 confidence, remapped, or picks all-repos
  while environments exist, task entry posts a compact Yes/Nope card that
  auto-starts the suggestion after ~5s; Nope edits the same message into a
  workspace picker (no timer). Router fallback shows the picker directly
  instead of silently launching in all repos.
- Pending choice lives in Redis (one-shot GETDEL claim; 64-byte-safe
  callback data; requester-only clicks; Nope re-keys state so the timer can
  never fire a rejected suggestion; superseding requests invalidate stale
  cards). Suggestion-button launches skip the card.
- New TelegramCommunicationProvider.editMessageText with HTML-to-plain
  fallback, used to finalize cards in place.

Verified with 56 API handler tests + 17 harness tests and a live end-to-end
run through the mock harness against the dev stack (card, Nope-to-picker,
Nevermind, timer no-op, zero jobs created).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@daniel-lxs
daniel-lxs merged commit e917c45 into develop Jul 9, 2026
1 check passed
@roomote-roomote-v1

roomote-roomote-v1 Bot commented Jul 9, 2026

Copy link
Copy Markdown

2 issues outstanding. See task

  • apps/api/src/handlers/telegram/routing-confirmation.ts:332 - The auto-confirm timer consumes the pending route and edits the card to “Starting…”, then awaits launchTelegramTask without the manual-click path's failure handling. If queueing/posting the task throws from the timer, scheduleTelegramRoutingAutoConfirm only logs the rejection, leaving the user with a finalized “Starting” card, no task, and no expired choice to retry.
  • .agents/skills/mock-telegram-testing/SKILL.md:19 - The new testing skill tells agents to send webhooks to http://localhost:3001, but this repo's local API defaults and local development docs use localhost:13001. Following the skill as written points the mock harness at the wrong endpoint, so the advertised Telegram harness workflow fails before it reaches the webhook.

mrubens pushed a commit that referenced this pull request Jul 9, 2026
Resolves conflicts by porting develop's changes onto the new data-model
contract:
- setup-new onboarding kickoff adopts develop's web-only Teams fallback
  (#48) with the new enqueue contract (user initiator, setup_onboarding
  workflow, provider stamp) instead of attributionOverride
- Telegram routing-confirmation launch helper (#22) ported to the new
  contract, keeping launchClass: 'human' for keepalive policy
- snapshot refresh keeps the automation initiator; dropped the re-merged
  forged-owner fallback
- setup redirect guard keeps the provider-agnostic completion check
- drizzle baseline regenerated to fold develop's 0001 (nullable
  environments.created_by_user_id + declarative_source) into the single
  0000 baseline
- develop-added tests updated to the new enqueue/factory shapes
@mrubens
mrubens deleted the feat/telegram-mock-harness-and-routing-confirmation branch July 12, 2026 04:19
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