Skip to content

fix(telegram): hidden text-link URLs reach the agent inline (#31071, salvage #74769) - #93346

Merged
teknium1 merged 3 commits into
mainfrom
nanoclaw-port/telegram-text-link-salvage
Sep 14, 2026
Merged

teknium1 merged 3 commits into
mainfrom
nanoclaw-port/telegram-text-link-salvage

Conversation

@teknium1

Copy link
Copy Markdown
Collaborator

Summary

Telegram messages with hidden hyperlinks ("click here" with a text_link entity) now reach the agent with the URL inlined — previously the agent saw only the anchor text and could not follow or fetch the link (#31071).

Salvage of #74769 by @DreamyMoonMouse onto current main (clean cherry-pick, authorship preserved). Ported here from the weekly NanoClaw scout (nanocoai/nanoclaw#3283 fixes the same platform gap); an open community PR already covered it, so it is salvaged instead of reimplemented.

Changes

  • plugins/platforms/telegram/adapter.py: new _expand_link_entities() — converts UTF-16 entity offsets to code-point indices (emoji/CJK-safe), appends (url) after each text_link anchor, idempotent on re-processing; wired into _build_message_event() (all text paths) plus both media-caption paths.
  • tests/gateway/test_telegram_text_link_expansion.py: 13 tests — plain text, captions, emoji offsets, malformed entities, repeat processing.

Why this PR over #31075

#31075 (earlier, by @dskwe) targets gateway/platforms/telegram.py, which no longer exists after the adapter moved to plugins/platforms/telegram/; it also only covers 2 of the 3 ingestion paths. This branch cherry-picks #74769, which targets the current location and covers _build_message_event centrally. @dskwe was first to the bug — credit noted here.

Validation

Before After
text_link in DM text agent sees "click here" "click here (https://…)"
caption entities URL lost URL inlined
targeted tests 31 passed (expansion + caption/channel suites)

Source scout reference: nanocoai/nanoclaw#3283.

Infographic

Hidden Telegram links now visible to the agent

@github-actions

github-actions Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

૮ >ﻌ< ა ci review

ran on 3f6c3ba — refactor(telegram): move text_link expansion to telegram_ent

⚠️ Warnings

OSV vulnerability scan · View job

76 known vulnerabilities found in pinned dependencies.

How to fix:

Review the findings in the Security tab. Update the affected dependencies if a patched version is available.


debug info

CI timings

CI timings · View report · View job

Wall time 5m3s vs 5m33s (-9.0%). 9 job(s) slower, 4 faster, 1 unchanged.

  • OS-specific tests / Windows-only tests: -32.0s
  • OS-specific tests / macOS-only tests: -13.0s
  • Check contributors / check-attribution: +8.0s
  • Detect affected areas: +5.0s
  • OSV scan / Scan lockfiles / osv-scan: +3.0s

@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/plugins Plugin system and bundled plugins platform/telegram Telegram bot adapter labels Aug 24, 2026
@Enough1122

Copy link
Copy Markdown
Contributor

AI code review — automated review for reference, author can ignore or act on any point.

Well-executed fix with unusually complete tests — the UTF-16 offset conversion (plugins/platforms/telegram/adapter.py:9131-9140) handles the emoji/surrogate cases that usually break this class of change, malformed entities fail closed, and reverse-sorted insertion keeps offsets valid. Three small things:

  1. plugins/platforms/telegram/adapter.py:9169-9172 — the idempotency guard expanded[end:].startswith(inline) misfires when a user genuinely writes anchor text immediately followed by the same parenthesized URL ("see тут (https://x.com)"): the real link entity is then silently dropped because the text looks pre-expanded. Rare, but since the comment claims repeated processing is the reason, a stronger discriminator would be checking that the char before end belongs to the anchor and the parenthetical wasn't part of any entity — or simply tracking processed update_ids upstream instead of shape-matching the text.

  2. plugins/platforms/telegram/adapter.py:9964 / :9979 vs :10687 — media handlers expand the caption explicitly and then _build_message_event also expands it internally for the same message, so the caption runs through _expand_link_entities twice per observed media event. Harmless today (second pass hits the idempotency guard), but it means point 1's false-positive window is hit twice for media captions; passing the already-expanded text through, or expanding only at the _build_message_event layer, would remove the duplication.

  3. plugins/platforms/telegram/adapter.py:9142-9143utf16_length recomputes a full scan per call; folding it into one pass with the index walk is trivial but honestly unnecessary at message sizes. Noting only so nobody "optimizes" the loop into subtle breakage.

DreamyMoonMouse and others added 3 commits September 13, 2026 19:47
…ling

The adapter facade is ~6.6k lines; new behaviour belongs in a topical sibling per the
facade+siblings layout. expand_link_entities() now lives in telegram_entities.py and
reuses the encode/decode UTF-16 slicing the adapter already uses for entity spans.

Also: skip inlining when the anchor text already is the URL (no 'url (url)' duplication),
trim the test file to the invariants and point it at the sibling.
@teknium1
teknium1 force-pushed the nanoclaw-port/telegram-text-link-salvage branch from 8bfd26e to 3f6c3ba Compare September 14, 2026 02:56
@teknium1
teknium1 merged commit d7ceee1 into main Sep 14, 2026
37 checks passed
@teknium1
teknium1 deleted the nanoclaw-port/telegram-text-link-salvage branch September 14, 2026 03:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/plugins Plugin system and bundled plugins P3 Low — cosmetic, nice to have platform/telegram Telegram bot adapter type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants