← Back to PRs

#20155: feat(telegram): add tg-network-guard transcript status + reply flow

by artemgetmann open 2026-02-18 16:00 View on GitHub →
size: XL
## Summary - add a new optional extension: `tg-network-guard` - show immediate Telegram feedback for inbound voice notes with `Transcribing...` - post a real, copyable `Transcript:` reply message after transcription completes - update the transcribing status message to `Transcribed.` - keep retries constrained to retry-safe Telegram endpoints only - add a focused extension test for inline media-path and metadata media-path cases ## Why this change Transcription can look silent/stuck when media-path materialization or network timing is slow. This change gives users immediate confirmation that transcription started, and then returns an actual text reply they can copy later. That directly solves a practical UX pain: users with long voice notes (often 1+ minute) shouldn’t need to replay audio just to recover what they said. The transcript reply is especially useful for users without premium voice tooling who still need searchable/copyable text history. ## Scope and risk - scope is limited to Telegram voice-note placeholder inputs and configured owner-chat matching - no generic `sendMessage` retries were added (to avoid duplicate content risk) - retry wrapper remains restricted to safe replay endpoints (`getUpdates`, `getFile`, `sendChatAction`, `answerCallbackQuery`, and Telegram file downloads) - extension is optional and config-driven ## Test plan - `pnpm exec vitest -c vitest.extensions.config.ts extensions/tg-network-guard/src/runtime.test.ts` - verifies: - transcribing status send - transcript reply send with preserved `reply_to_message_id` - status edit to `Transcribed.` - metadata media-path fallback behavior <!-- greptile_comment --> <h3>Greptile Summary</h3> Adds a new optional extension `tg-network-guard` that provides two capabilities: (1) retry-safe fetch wrapping for Telegram API endpoints (file downloads, `getUpdates`, `getFile`, `sendChatAction`, `answerCallbackQuery`) with exponential backoff, and (2) a voice-note transcription flow that shows "Transcribing..." status, runs Whisper CLI, posts the transcript as a reply, then edits status to "Transcribed." The extension is well-scoped: retries are restricted to idempotent Telegram endpoints (no `sendMessage` retry to avoid duplicate content), the global fetch patch uses `Symbol.for` to prevent double-installation, and the transcription flow has deduplication, cooldowns, and chunked output for long transcripts. - **Owner chat ID matching uses substring check** (`from.includes(ownerChatId)`) which could match unintended Telegram user IDs whose ID is a superstring of the configured owner. Should use boundary-aware matching. - **Hardcoded personal Telegram ID** `1336356696` appears as the default in both `openclaw.plugin.json` and as a runtime fallback in `runtime.ts`. This exposes a personal identifier and should be removed in favor of requiring explicit configuration. - Test coverage is focused and verifies the core happy path (inline media-path and metadata media-path scenarios), though edge cases like failed transcription and ack cooldowns are not covered. <h3>Confidence Score: 3/5</h3> - Generally safe but has a substring-matching logic bug in owner ID gating and a hardcoded personal ID that should be addressed before merge. - The extension is well-structured and follows repo conventions. The retry logic is correctly scoped to safe endpoints. However, the substring-based owner ID check could match the wrong user under certain conditions, and the hardcoded Telegram ID is both a privacy leak and a configuration footgun for other deployers. These are addressable fixes but should be resolved. - `extensions/tg-network-guard/src/runtime.ts` (owner ID matching logic and hardcoded fallback), `extensions/tg-network-guard/openclaw.plugin.json` (hardcoded default ID) <sub>Last reviewed commit: ed2e22e</sub> <!-- greptile_other_comments_section --> <sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub> **Context used:** - Context from `dashboard` - CLAUDE.md ([source](https://app.greptile.com/review/custom-context?memory=fd949e91-5c3a-4ab5-90a1-cbe184fd6ce8)) <!-- /greptile_comment -->

Most Similar PRs