Skip to content

[feat] Add TelegramModule for Telegram Bot API integration#10

Open
johnsonice wants to merge 1 commit intomainfrom
feat/20260329_telegram_module
Open

[feat] Add TelegramModule for Telegram Bot API integration#10
johnsonice wants to merge 1 commit intomainfrom
feat/20260329_telegram_module

Conversation

@johnsonice
Copy link
Copy Markdown
Collaborator

Summary

Add Telegram as the second IM channel (after Matrix), enabling agents to receive and respond to messages via Telegram Bot API. Mirrors the MatrixModule architecture pattern.

V1 Scope

  • Full duplex: inbound conversation + outbound notifications
  • One bot token per agent (registered via telegram_register MCP tool)
  • Long-polling transport with sub-second latency (Telegram getUpdates(timeout=30))
  • Text messages + /start and /help commands
  • DM support + group chat with @mention-required activation
  • Typing indicator (persistent until agent responds), message chunking (>4096 chars), HTML formatting
  • Two-tier dedup (in-memory + DB), per-chat rate limiting (20/30min safety net)
  • 3 MCP tools: telegram_register, telegram_send_message, telegram_reply_to_message

New Files (13)

  • module/telegram_module/ — 9 files: module, trigger, client, hooks, MCP tools, credential manager, dedup, context builder
  • utils/database_table_management/create_telegram_credentials_table.py
  • utils/database_table_management/create_telegram_processed_updates_table.py
  • start/telegram-trigger.sh
  • docs/superpowers/specs/2026-03-29-telegram-integration-design.md

Modified Files (9)

  • schema/hook_schema.py — added TELEGRAM to WorkingSource enum
  • schema/channel_tag.py — added ChannelTag.telegram() factory
  • module/__init__.py — registered TelegramModule in MODULE_MAP
  • module/_module_impl/loader.py — added to DEFAULT_MODULE_LIST + ALWAYS_LOAD_MODULES
  • module/module_runner.py — MCP port 7812
  • settings.pytelegram_bot_token, telegram_allowed_user_ids
  • start/all.sh, start/control.sh, run.sh — telegram-trigger service integration

Design Decisions

  • Full Module (not lightweight adapter or generic IM gateway) — architectural consistency with MatrixModule
  • Long-polling (webhook-ready) — no public URL needed, sub-second latency via Telegram server-side long-poll
  • HTML parse mode with plain text fallback — more reliable than MarkdownV2
  • Agent sends replies via MCP tools (trigger does NOT auto-reply) — matches MatrixTrigger pattern
  • Always-loaded module — ensures telegram_register tool is available before any credential exists

Pre-merge Checklist

  • Import check passes (import xyz_agent_context.module; .narrative; .services)
  • Ruff lint passes
  • No secrets in commit
  • DB tables auto-create on trigger startup (CREATE TABLE IF NOT EXISTS)
  • Code review completed — all warnings addressed

Test Plan

  • Set TELEGRAM_BOT_TOKEN via agent chat (telegram_register tool)
  • Send /start to bot in Telegram → welcome message
  • Send text message in DM → typing indicator + agent reply (single message, no duplicate)
  • Add bot to group, send @botname hello → bot responds
  • Send message without @mention in group → bot ignores
  • Verify telegram-trigger tmux window shows in control panel
  • Verify logs at ~/.narranexus/logs/telegram_trigger/

🤖 Generated with Claude Code

Add Telegram as the second IM channel (after Matrix), enabling agents
to receive and respond to messages via Telegram Bot API.

V1 scope:
- Full duplex: inbound conversation + outbound notifications
- One bot token per agent (registered via telegram_register MCP tool)
- Long-polling transport with sub-second latency
- Text messages + /start and /help commands
- DM support + group chat with @mention-required activation
- Typing indicator, message chunking (>4096 chars), HTML formatting
- Two-tier dedup (in-memory + DB), per-chat rate limiting

New files:
- module/telegram_module/ (9 files): module, trigger, client, hooks,
  MCP tools, credential manager, dedup, context builder
- Table management scripts for telegram_credentials and
  telegram_processed_updates
- start/telegram-trigger.sh + tmux integration

Modified: WorkingSource enum, ChannelTag factory, MODULE_MAP,
ALWAYS_LOAD_MODULES, module_runner ports, settings, control panel,
run.sh service launcher.

Design spec: docs/superpowers/specs/2026-03-29-telegram-integration-design.md

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
BinLiang2021 added a commit that referenced this pull request Apr 10, 2026
- Add 铁律 #10: tier-2 mirror md sync requirement
- Add 三级文档体系 section pointing to .nac_doc/README.md
- Add 工作流启动 section (scan index → read playbook → read mirror → sync)
- Add 深度文档索引 with "何时读" triggers for every reference and playbook
- Trim 新建 Module 步骤 to a pointer + 铁律 summary (moved to playbook)
- Add .nac_doc/ and scripts/nac_doc_*.py to 目录结构参考

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
BinLiang2021 added a commit that referenced this pull request Apr 10, 2026
Generated by make scaffold-nac-doc. All stubs have frontmatter stub: true
and <!-- TODO: intent --> placeholders. Phase 2 (hand-writing critical file
intent) happens in a separate session; Phase 3 (lazy fill) is triggered by
CLAUDE.md ironclad rule #10 during normal development.

Covered by check_nac_doc.py Layer 1 structural invariants (all hold).

326 stub files total across src/xyz_agent_context/, backend/,
frontend/src/, and tauri/src-tauri/src/.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
BinLiang2021 added a commit that referenced this pull request Apr 10, 2026
… fallback

Two improvements from dogfood testing (simulating a zero-context new
contributor reading the docs):

1. .nac_doc/_overview.md now leads with a "项目速览 60 秒版" section:
   - One-line project description
   - ASCII architecture diagram (API → AgentRuntime → Services → Repo)
   - The four dev process commands (dev-backend, dev-frontend, dev-mcp, dev-poller)
   - Reminder about 铁律 #7 (双运行方式对齐)
   Previously the overview jumped straight to the reading path, leaving a
   new contributor without a project-level grounding until they followed
   the reading path 2-3 layers deep.

2. CLAUDE.md "深度文档索引" fallback note rewritten from "按 .nac_doc/README.md
   现场推断" (which doesn't actually work — README.md is project-agnostic
   methodology) to a concrete 4-step fallback chain:
     i.   Read CLAUDE.md itself (four sections that cover most on-boarding)
     ii.  Read the corresponding mirror md (frontmatter points at source)
     iii. Read the source file directly (docstrings are in English per 铁律 #1)
     iv.  On completion, fill in the mirror md per 铁律 #10
   Plus explicit note that README.md is methodology, NOT project knowledge.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
BinLiang2021 added a commit that referenced this pull request Apr 13, 2026
… cleanup)

Fixes today's documented doc debt. Per CLAUDE.md 铁律 #10:
"对 .py/.tsx/.ts/.rs 做行为性修改时,必须...更新 md。新增代码文件 → 同一 commit 新增对应 mirror md"
— violated across 6 commits today. This commit settles that debt.

New mirror md (13 files created over today's dev but mirror never landed):
  Backend:
    backend/routes/_dashboard_schema.md
    backend/routes/_dashboard_helpers.md
    backend/routes/_rate_limiter.md
  Frontend dashboard components:
    AttentionBanners.md · JobsSection.md · MetricsRow.md · QueueBar.md
    RecentFeed.md · SessionSection.md · Sparkline.md · DashboardSummary.md
    expandState.md · healthColors.md

Updated mirror md (stubs promoted to full intent + stale references fixed):
  frontend/src/components/dashboard/
    AgentCard.md        — stub → full (rewritten 3 times in v2/v2.1/v2.1.1/v2.1.2;
                          documents OwnedCard/PublicCard split as permission boundary,
                          expand semantics, stopPropagation contract, rail-dim behavior)
    ConcurrencyBadge.md — stub → full (v2.1.1 removed owned branch; reasoning
                          for "×N" confusion + public bucket as privacy measure)
    StatusBadge.md      — stub → full (8-kind → icon/color table + extension guide)
    DurationDisplay.md  — stub → full (Date.now() purity exception + polling tick
                          refresh cadence trade-off)
  frontend/src/pages/DashboardPage.md
                       — updated render section to reflect v2.1.1+ structure
                         (AgentCard self-manages expand, AgentCardExpanded removed,
                         DashboardSummary added); added single-expandedId strategy note

Dead code removal:
  frontend/src/components/dashboard/AgentCardExpanded.tsx — orphaned since v2.1.1
    retire; DashboardPage.tsx already explicitly did not render it. Removed
    file + its mirror md in this commit per 铁律 #10 ("删除代码文件 → 同一
    commit 删除对应 mirror md"). Stale "intentionally NOT rendered" comment in
    DashboardPage.tsx also removed.

Not in this commit (acknowledged gaps, separate cleanup):
  - Tier-3 reference (`.mindflow/project/references/dashboard_system.md`) — dashboard
    is now substantial enough to warrant one, but user scoped this task to "补文档"
    (fix debt), not "add tier-3". Separate followup.
  - pre-commit hook to mechanically enforce 铁律 #10 going forward. Same followup.
  - last_verified timestamp refresh on mirrors whose underlying code was modified
    but intent didn't change (active_sessions, dashboardStore, lib/tauri, commands/tray,
    backend/main, backend/auth, backend/routes/websocket). Their intent descriptions
    remain accurate; leaving timestamps alone rather than rubber-stamping.

tsc -b: exit 0.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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